将字符串值转换为未知(在编译时)对象类型

时间:2011-08-24 11:57:39

标签: java class

我有一个类类型,我在字符串中有一个值:

Class<?> type = Integer.class // <-- in reality, that type is 
                              // determined at runtime
String value = "3";           // <-- same here, actually read from a file

我的目标是实例化一个'type'的实例,并用'value'的值填充它...所以我有相当于

Integer i = new Integer(value);

唯一可行的方法是做一长串if语句:

if (type == Integer.class) {
  // do this
}

还是有另一种聪明/正确的方法吗?可能的类类型可能完全不同,如整数/日期等...

EDIT1

这里有更多背景信息:

我有一个包含许多值的文件,这些值是不同数据类型实例的文本表示:

1|3.4|2011-08-24

在我的程序中,我得到了一个类类和一个方法,在编译时我都不知道。

我想在该类型的实例上调用该方法,并将文件中的值作为参数。但是对于那个我必须有相应的对象到该值,在示例中可以是Integer / int,float / double,Date。 我可以通过反射获得方法的形式参数的这些数据类型,但我不确定从字符串到对象的转换的最佳方法......

也许这个伪程序会搞清楚:

String[] values = getValuesFromFile;
Class<?> type = getType();
Method method = getMethod();
Class<?>[] formalParameterTypes = getMethodParameterTypes();
Object[] objects;
for(int i; i < values.length; i++)
  objects[i] = convert(values[i],formalParameterTypes[i]);
method.invoke(objects);

5 个答案:

答案 0 :(得分:1)

发明动态类加载和反射来解决这些问题。 E.g。

Class<?> type = Class.forName("MyClassName");
Object obj = type.newInstance();

现在,如果要在对象中设置字段,则有两个选项:

  • 如果潜在类共享一个公共基类/接口,则可以将该对象强制转换为该接口并通过接口方法对其进行操作,
  • 如果潜在类与继承无关但具有相同的方法/字段,则可以通过bean introspection设置字段值,或者可以使用反射调用该方法。

答案 1 :(得分:1)

如果您的类型仅限于原始数据类型的包装类,则所有类都具有静态valueOf(String)方法,该方法可用于解析String并返回有效实例。

我会使用反射来查找和调用方法并使用结果:

public static void main(String[] args) throws Exception {
    int i = parse(Integer.class, "4711");
    double d = parse(Double.class, "47.11");
    boolean b = parse(Boolean.class, "true");
    System.out.println(i);
    System.out.println(d);
    System.out.println(b);
}

public static <T> T parse(Class<T> type, String value) {
    try {
        return (T)type.getDeclaredMethod("valueOf", String.class).invoke(null, value);
    }
    catch(Exception e) {
        throw new RuntimeException(e);
    }
}

答案 2 :(得分:1)

根据我的理解,你想要这样的东西:

Object instance = createMagically(getClass(), getString());

其中getClass()可能会返回Integer.classgetString()可能会返回值"42"。但价值对Date.class"15 Apr 2011"也是预期的。

您必须使用条件(if / else if),因为通常每种类型都有自己的转换规则。没有通用构造函数可以从String创建实例。

所以你可以实现这样的“工厂”方法:

public static Object createInstance(Class<?> type, String content) {
  if (type.equals(Integer.class)) return new Integer(content);
  else if // ...
  return content;  // just an idea for a default if the type can't be handled
}

然后,再次使用返回值,如果要确定实际类型,可能需要更多if / else if(if (value instancof Integer) ...)

所以,从我的观点来看 - 你做了很多检查,但你可以隐藏实用程序类中的丑陋魔法。

答案 3 :(得分:0)

使用JSON,您可以在运行时将字符串转换为对象,而不必知道开头的原始类型。

答案 4 :(得分:0)

如果值只有字符串表示,您可以这样做:

String typeName = ...
String value = ...
Class<?> type = Class.forName(typeName);
Constructor<?> constructor = type.getConstructor(String.class);
Object instance = constructor.newInstance(value);
// cast the instance to actual class