java:我如何动态地将变量从一种类型转换为另一种类型?

ufk*_*ufk 72 java dynamic-cast casting

我想为java变量进行动态转换,转换类型存储在不同的变量中.

这是常规铸造:

 String a = (String) 5;
Run Code Online (Sandbox Code Playgroud)

这就是我要的:

 String theType = 'String';
 String a = (theType) 5;
Run Code Online (Sandbox Code Playgroud)

可能吗?如果是这样怎么样?谢谢!

更新

我正在尝试用我收到的hashMap填充一个类.

这是构造函数:

public ConnectParams(HashMap<String,Object> obj) {

    for (Map.Entry<String, Object> entry : obj.entrySet()) {
        try {
            Field f =  this.getClass().getField(entry.getKey());                
            f.set(this, entry.getValue()); /* <= CASTING PROBLEM */
        } catch (NoSuchFieldException ex) {
            log.error("did not find field '" + entry.getKey() + '"');
        } catch (IllegalAccessException ex) {
            log.error(ex.getMessage());         
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

这里的问题是一些类变量是Double类型,如果接收到数字3,它将其视为Integer,我有类型问题.

use*_*421 104

是的,可以使用Reflection

Object something = "something";
String theType = "java.lang.String";
Class<?> theClass = Class.forName(theType);
Object obj = theClass.cast(something);
Run Code Online (Sandbox Code Playgroud)

但这没有多大意义,因为生成的对象必须保存在Object类型的变量中.如果您需要变量属于给定类,则可以转换为该类.

如果要获取给定的类,例如:

Object something = new Integer(123);
String theType = "java.lang.Number";
Class<? extends Number> theClass = Class.forName(theType).asSubclass(Number.class);
Number obj = theClass.cast(something);
Run Code Online (Sandbox Code Playgroud)

但是这样做仍然没有意义,你可以直接转向Number.

铸造物体不会改变任何东西; 它只是编译器对待它的方式.
做这样的事情的唯一原因是检查对象是否是给定类或其任何子类的实例,但使用instanceof或更好Class.isInstance().

更新

根据你的上一次更新,真正的问题是你的HashMap中有一个应该分配给Double的Integer.在这种情况下,您可以做的是检查字段的类型并使用xxxValue()Number 的方法

...
Field f =  this.getClass().getField(entry.getKey());
Object value = entry.getValue();
if (Integer.class.isAssignableFrom(f.getType())) {
    value = Integer.valueOf(((Number) entry.getValue()).intValue());
} else if (Double.class.isAssignableFrom(f.getType())) {
    value = Double.valueOf(((Number) entry.getValue()).doubleValue());
} // other cases as needed (Long, Float, ...)
f.set(this, value);
...
Run Code Online (Sandbox Code Playgroud)

(不确定我是否喜欢在Map中输入错误类型的想法)


Bal*_*usC 21

你需要为此写一些ObjectConverter.如果您同时拥有要转换的对象并且您知道要转换为的目标类,则这是可行的.在这种特殊情况下,您可以通过获取目标类Field#getDeclaringClass().

你可以在这里找到这样一个例子ObjectConverter.它应该给你基本的想法.如果您想要更多的转换可能性,只需使用所需的参数和返回类型添加更多方法.


aku*_*uhn 13

关于您的更新,在Java中解决此问题的唯一方法是编写涵盖所有包含大量ifelseinstanceof表达式的情况的代码.您尝试执行的操作看起来好像用于使用动态语言编程.在静态语言中,您尝试做的几乎是不可能的,并且可能会为您尝试的操作选择完全不同的方法.静态语言不像动态语言那样灵活:)

Java最佳实践的好例子是BalusC(即ObjectConverter)的答案和Andreas_D(即Adapter)下面的答案.


这没有任何意义,在

String a = (theType) 5;
Run Code Online (Sandbox Code Playgroud)

a静态绑定的类型String因此对此静态类型进行动态转换没有任何意义.

PS: 您的示例的第一行可以写为Class<String> stringClass = String.class;但仍然不能用于stringClass转换变量.


Jar*_*ell 12

您可以使用该Class.cast()方法执行此操作,该方法将提供的参数动态转换为您拥有的类实例的类型.要获取特定字段的类实例,请getType()在相关字段上使用该方法.我在下面给出了一个例子,但请注意它省略了所有错误处理,不应该未经修改地使用.

public class Test {

    public String var1;
    public Integer var2;
}

public class Main {

    public static void main(String[] args) throws Exception {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("var1", "test");
        map.put("var2", 1);

        Test t = new Test();

        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Field f = Test.class.getField(entry.getKey());

            f.set(t, f.getType().cast(entry.getValue()));
        }

        System.out.println(t.var1);
        System.out.println(t.var2);
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 6

您可以编写一个简单的castMethod,如下所示.

private <T> T castObject(Class<T> clazz, Object object) {
  return (T) object;
}
Run Code Online (Sandbox Code Playgroud)

在你的方法中你应该像它一样使用它

public ConnectParams(HashMap<String,Object> object) {

for (Map.Entry<String, Object> entry : object.entrySet()) {
    try {
        Field f =  this.getClass().getField(entry.getKey());                
        f.set(this, castObject(entry.getValue().getClass(), entry.getValue()); /* <= CASTING PROBLEM */
    } catch (NoSuchFieldException ex) {
        log.error("did not find field '" + entry.getKey() + '"');
    } catch (IllegalAccessException ex) {    
        log.error(ex.getMessage());          
    }    
}

}
Run Code Online (Sandbox Code Playgroud)


And*_*s_D 5

它有效,您的方法甚至有一个通用模式:Adapter 模式。但是当然,(1) 它不适用于将 java 原语转换为对象,并且 (2) 该类必须具有适应性(通常通过实现自定义接口)。

使用此模式,您可以执行以下操作:

Wolf bigBadWolf = new Wolf();
Sheep sheep = (Sheep) bigBadWolf.getAdapter(Sheep.class);
Run Code Online (Sandbox Code Playgroud)

和 Wolf 类中的 getAdapter 方法:

public Object getAdapter(Class clazz) {
  if (clazz.equals(Sheep.class)) {
    // return a Sheep implementation
    return getWolfDressedAsSheep(this);
  }

  if (clazz.equals(String.class)) {
    // return a String
    return this.getName();
  }

  return null; // not adaptable
}
Run Code Online (Sandbox Code Playgroud)

对你来说特别的想法——那是不可能的。您不能使用 String 值进行转换。