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

Java 将字符串值转换为未知(编译时)对象类型,java,class,Java,Class,我有一个类类型和一个字符串中的值: Class<?> type = Integer.class // <-- in reality, that type is // determined at runtime String value = "3"; // <-- same here, actually read from a file 唯一可行的方法是使用一长串if语句: if (type

我有一个类类型和一个字符串中的值:

Class<?> type = Integer.class // <-- in reality, that type is 
                              // determined at runtime
String value = "3";           // <-- same here, actually read from a file
唯一可行的方法是使用一长串if语句:

if (type == Integer.class) {
  // do this
}
还是有其他聪明/正确的方法?可能的类类型可能完全不同,如整数/日期等

编辑1

这里有更多的上下文:

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

1|3.4|2011-08-24
在我的程序中,我在那个类中得到了一个类类型和一个方法,这在编译时对我来说都是未知的

我想在该类型的实例上调用该方法,将文件中的值作为参数。但对于这一点,我必须有对应于该值的对象,在示例中,它可以是整数/int、浮点/双精度、日期。 我可以通过反射为方法的形式参数获取这些数据类型,但我不确定从字符串到对象的转换的最佳方式

也许这个伪程序会把事情弄清楚:

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);

动态类加载和反射就是为了解决这些问题而发明的。例如

Class<?> type = Class.forName("MyClassName");
Object obj = type.newInstance();
现在,如果要在对象中设置字段,有两个选项:

如果潜在类共享一个公共基类/接口,则可以将对象向下转换到该接口,并通过接口方法对其进行操作, 如果潜在类与继承无关,但具有相同的方法/字段,则可以通过设置字段值,也可以使用反射调用该方法。
动态类加载和反射就是为了解决这些问题而发明的。例如

Class<?> type = Class.forName("MyClassName");
Object obj = type.newInstance();
现在,如果要在对象中设置字段,有两个选项:

如果潜在类共享一个公共基类/接口,则可以将对象向下转换到该接口,并通过接口方法对其进行操作, 如果潜在类与继承无关,但具有相同的方法/字段,则可以通过设置字段值,也可以使用反射调用该方法。
如果您的类型仅限于原始数据类型的包装类,则所有类都有一个静态valueOfString方法,该方法可用于解析字符串并返回有效实例

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

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);
    }
}

如果您的类型仅限于原始数据类型的包装类,则所有类都有一个静态valueOfString方法,该方法可用于解析字符串并返回有效实例

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

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);
    }
}

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

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

据我所知,您希望这样:

Object instance = createMagically(getClass(), getString());
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
}
其中getClass可能返回Integer.class和getString值42。但价值对Date.class和2011年4月15日也是预期的

在某一点上,您必须使用条件if/else if,因为一般来说,每个类型都有自己的转换规则。没有通用构造函数可以从字符串创建实例

因此,您可以实现如下工厂方法:

Object instance = createMagically(getClass(), getString());
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值instancof Integer


因此,从我的观点来看,你必须做很多检查,但你可以在实用程序类中隐藏丑陋的魔力。

据我所知,你需要这样的东西:

Object instance = createMagically(getClass(), getString());
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
}
其中getClass可能返回Integer.class和getString值42。但价值对Date.class和2011年4月15日也是预期的

在某一点上,您必须使用条件if/else if,因为一般来说,每个类型都有自己的转换规则。没有通用构造函数可以从字符串创建实例

因此,您可以实现如下工厂方法:

Object instance = createMagically(getClass(), getString());
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值instancof Integer


因此,从我的观点来看,您必须进行大量检查,但您可以在实用程序类中隐藏丑陋的魔力。

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

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

如果值只有字符串表示形式,则需要执行以下操作:

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

请围绕用法显示更多上下文。请围绕用法显示更多上下文。如果您尝试Integer.class.newInstance会发生什么情况?@jarnbjo,您当然会得到一个异常。上面的示例指向正确的方向,而不是生产代码。@jarnbjo-这要求在编译时知道该类。但事实并非如此。如果您尝试Integer.class.newInstance会发生什么?@jarnbjo,您当然会得到一个异常。以上是指向正确方向的示例,而不是生产代码。@jarnbjo-这需要
t表示该类在编译时已知。但事实上不是。类型不限于包装,他已经提到了日期。类型不限于包装,他已经提到了日期。是的,这就是我想要的方式。。。我只是想有一个更好的方法我不知道…是的,这就是我想要的方法。。。我只是觉得有更好的方法我不知道。。。