簡體   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