簡體   English   中英

如果沒有參數,如何獲得泛型類?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM