2016-10-14 40 views
5

我想請求一個項目類的集合(類型的具體反映)。但關於刪除類型似乎不可能,也關於我在堆棧上閱讀的一些主題。有一些變通辦法(here),但我很好奇,如果有人知道它是如何例如通過DWR完成:DWR如何投入數據和逃避類型擦除

http://directwebremoting.org/dwr/documentation/server/configuration/dwrxml/signatures.html

或情況,有一些更好的解決辦法將是巨大的。

比方說,我們有這樣的事:

public String foo(List<String> possibleFoos) { 

和所有我需要的是找到了該參數possibleFoos是一個字符串列表,而不是隻列出

回答

6

雖然這是事實,Java將在刪除類型(因此將List<String>變成List),在很多情況下,它實際上會在運行時存儲通用類型,從而允許您恢復丟失的信息。 您可以檢索實際泛型類型爲這些:

  • 方法參數(你的情況)
  • 方法的返回類型
  • 字段類型
  • 超類/接口

這意味着,如果你只是有一個List類型的對象,沒有什麼可以做到的,以獲得它的通用類型(object.getClass()會讓你List就是這樣) - 它已經pe永久失落。但是,如果您試圖找出方法參數的泛型類型或以上任何一種,則通常使用反射可以使用。至於你的情況不涉及類型變量或其他併發症,這是非常簡單的,以獲得實際類型:如果你有多個參數和地圖,而不是

ParameterizedType listArgument = (ParameterizedType) ClassDeclaringFoo.class.getMethod("foo", List.class).getGenericParameterTypes()[0]; 
Type listType = listArgument.getActualTypeArguments()[0]; //This will be a Class representing String, the type of the List 

public String foo(Object bar, Map<String, Number> possibleFoos) { ... } 

代碼將與此類似:

ParameterizedType mapArgument = (ParameterizedType) ClassDeclaringFoo.class.getMethod("foo", Object.class, Map.class).getGenericParameterTypes()[1]; //1 is the index of the map argument 
Type keyType = mapArgument.getActualTypeArguments()[0]; //This will be a Class representing String, the type of the Map key 
Type valType = mapArgument.getActualTypeArguments()[1]; //This will be a Class representing Number, the type of the Map value 

它是安全的假設這是DWR使用爲好,因爲類型是方法的參數。

類似的方法也可用於其他上市情況:

  • Class.getMethod(...).getGenericReturnType()將讓你真正的返回類型
  • Class.getField(fieldName).getGenericType()將讓你真正的類型的字段的
  • Class.getGenericSuperClass()將讓你真正的超級型號
  • Class.getGenericInterfaces()將爲您帶來真實的接口類型

等同的方法存在允許在Java中8引入訪問AnnotatedType(通用型加註解的類型使用):

  • Class.getMethod(...).getAnnotatedParameterTypes()
  • Class.getMethod(...).getAnnotatedReturnType()
  • Class.getField(fieldName).getAnnotatedType()
  • Class.getAnnotatedSuperClass()
  • Class.getAnnotatedInterfaces()

現在,當你的案例與例子一樣簡單時,這一切都很華麗。 但是,試想一下,如果你的例子是這樣的:

public T foo(List<T> possibleFoos) {...} 

在這種情況下,getGenericParameterTypes()[0].getActualTypeArguments()[0]會給你T這是相當無用的。爲了解決T代表什麼,你必須查看類定義,也許是超類,同時跟蹤每個類中類型變量的命名方式,因爲每個類中的名稱可能不同。

爲了與普通的反射式操作更容易,你可以用一個精彩的庫調用GenTyRef,做了艱苦的工作適合你,如果你需要AnnotatedType的支持下,你可以使用我的叉子稱爲GeAnTyRef(都是在Maven中中央)。他們還包括一個類型工廠,允許您構建(Annotated)Type的實例,使用普通的Java API無法輕鬆完成實例。還有一個方便的super type token實現允許您獲得(Annotated)Type文字。

有了這些,你可以用泛型類型的一切,Java允許沒有我上面所解釋的麻煩:

  • GenericTypeReflector#getExactParameterTypes(...)
  • GenericTypeReflector#getExactReturnType(...)
  • GenericTypeReflector#getExactFieldType(...)
  • GenericTypeReflector#getExactSuperType(...)

而且更多的操作,如figuri如果其中一個Type是另一個超類型(類似於Class#isAssignableFrom,但是泛型類型),則解析特定類型變量等。

+0

謝謝您的全面回答,那正是我想知道的! – Radim

+0

我使用了「hassle」版本,它對列表工作正常,但它不適用於map,因爲getParameterizedType返回類對象。由於我對以前的文章有了更好的瞭解,我試圖再次搜索如何使用地圖,但我沒有找到任何東西。你能再幫我一次嗎? – Radim

+1

@Radim我已經更新了我的答案,以包含一個具有Map 作爲第二個參數的示例。 那是你在追求什麼? – kaqqao