[英]How to get class of generic type when there is no parameter of it?
我剛學會了這種精美的語法
Collections.<String>emptyList()
獲取一個空List
,其中的元素應該是String
類型。 Java的源代碼如下:
public static final List EMPTY_LIST = new EmptyList<Object>();
:
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
現在,如果我以這種方式編寫方法,其中泛型類型沒有出現在參數列表中,有什么方法可以訪問成為T
的實際類?
我說,到目前為止,我的代碼處理方法本來就是這樣
private <T> T get(String key, Class<T> clazz) {
// here I can do whatever I want with clazz, e.g.:
return clazz.cast(value);
}
如果我刪除了clazz
-parameter,我就無法進行強制轉換cast()
。 顯然我能做到
return (T) value;
但是這給了我通常的警告Type safety: Unchecked cast from Object to T
。 好的, @SuppressWarnings("unchecked")
在這里有所幫助,但實際上我想用該方法的預期返回類型做一些事情。 如果我添加一個局部變量
T retValue;
我必須用一些東西初始化它, null
無濟於事。 在我分配之后
@SuppressWarnings("unchecked")
T retValue = (T) value;
我可以做,例如
retValue.getClass().getName()
但如果演員表失敗,我最終沒有關於T
信息。
由於Java(或至少我的Java 6)在運行時不再具有通用信息,因此我目前無法想到這樣做的方法。 有辦法嗎? 或者我必須堅持我的“舊”方法嗎?
請注意,我列出的示例非常簡單,沒有多大意義。 我想在這里做更復雜的事情,但這超出了范圍。
如果您希望在運行時使用泛型類型,則需要將其作為字段使用,或者為特定的類型組合創建類型的子類。
例如
List<String> list = new ArrayList<String>() {}; // creates a generic sub-type
final Class type = (Class) ((ParameterizedType) list.getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
System.out.println(type);
版畫
class java.lang.String
不幸的是,你不能。 所有泛型和類型參數都在運行時擦除。 所以在運行時,你的T
的類型就是Object
retValue.getClass().getName()
將始終返回對象的運行時類型,而不是參數類型的類名。
如果你想獲取參數類,除了使用你的第一個解決方案之外別無他法。 (也就是說,明確傳遞類對象。)
正如您所提到的,Java泛型只是構建時間。 它們在運行時不使用。
因此,您使用的舊方法將是您實現此目標的唯一方法。
我發現從T獲取Class<?>
有一個解決方案:
public class Action<T>{
}
public Class<?> getGenericType(Object action) throws ClassNotFoundException{
Type type =
((ParameterizedType)action.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
String sType[] = type.toString().split(" ");
if(sType.length != 2)
throw new ClassNotFoundException();
return Class.forName(sType[1]);
}
上面代碼的用法:
Action<String> myAction = new Action<String>();
getGenericType(myAction);
我沒有用原始類型(int,byte,boolean)測試它。
我認為它不是很快,但你不必將Class<?>
傳遞給構造函數。
編輯:
上面的用法不正確,因為Action<String>
不能使用通用超類。 通用超類僅適用於繼承類, class ActionWithParam extends Action<String>{}
。 這就是我改變主意的原因,現在我建議將類參數傳遞給構造函數。 感謝newacct的糾正。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.