繁体   English   中英

给定一个字符串作为泛型类的类型名称,我如何在运行时创建实例。 如果不可能,还有其他方法吗?

[英]Given a string as the type name of a generic class, how can I create the instance in runtime. If it is not possible, Is there another way?

用户通过配置支持userType和userFunction:

{"userType": "com.user.Person", "userFunction": "com.user.userFunction"}

我们希望获取用户数据并将数据提供给userFunction:

public class DataConsumer<T> {
    //get data from some place, such as kafka
    T data;
}
process() {
    String userType = userInput();
    DataConsumer<userType> dataConsumer = new DataConsumer<userType>(); // error because generic class's type name don't support String or Class 
    userFunction(dataConsumer.data); // We get this function by reflection
}

// This is ok in the user side
userFunction(userType data) {
    data;
}

如何实现该功能而不会出现错误? 如果不可能,还有其他方法吗?

最后,我使用对象代表所有类型名称。 但是用户必须手动将对象类型转换为userType。 有没有更好的办法?

{
    String userType = userInput();
    DataConsumer<Object> dataConsumer = new DataConsumer<Object>(); // ok
    userFunction(dataConsumer.data); 
}

userFunction(Object data) {
    (userType)data;
}

您可以使用Reflection API获取类,方法和字段的实例;

首先,您可以使用

 Class c = Class.forName("Class Name");

您可以使用以下方法从该类中获取方法

 c.getDeclaredMethod("Method Name");

领域也是如此

 c.getDeclaredField("Field Name");

嗯,您应该知道Java在大多数情况下,泛型只是编译器中的语法糖,因此,如果您不知道运行时类型,请使用通配符或原始类型:
MyClass<?> myClass = new MyClass<>(); MyClass myClass = new MyClass();
但是,如果用户输入始终是诸如String之类的已知类型,则可以执行以下操作:
MyClass<String> myClass = new MyClass<>();
您还可以在类中创建通用构造函数,如下所示:

public class MyClass<T> {
    T data;
    public <T> MyClass(T data) {this.data = data;}
}

因此,泛型类型将是您传递给它的数据类型-但这仅在编译时存在,在运行时Java IGNORES中,此处的所有泛型都是这样,例如,这是有效的Java代码:

List<String> strings = new ArrayList<>();
strings.add(“a”);
List<Integer> integersKindOf = (List)strings;
integersKindOf.remove(“a”);

Java仅保存通用类型的字段,超类( class MyMap extends HashMap<String, Integer> -您可以使用通用参数获取该超类型)和方法。 但是它们不在运行时中使用,而是可以使用反射来读取该类型。
对于局部变量,这是不可能的,并且由于这种类型的擦除而将是无用的。

不安全的泛型转换也有常见的模式,但是使用时要非常小心:

public <T> T doSomething(String type) {
    return (T) Class.forName(type).newInstance();
}

然后可以这样使用:
ArrayList<Whatever> list = doSomething("java.util.ArrayList");
但也可以这样使用:
Integer list = doSomething("java.util.ArrayList");
这将在运行时引发异常,这就是为什么它非常不安全的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM