我會認爲這是因爲jdk 1.7類型的推理性質。
正如你可能已經知道,Arrays.asList(T ... elems)
方法是通用的,但我們很少明確地指定我們想與之合作的方法類型參數,因此,我們編譯器的類型推理功能依賴。
所以,當編譯器看到的Arrays.asList(Override.class)
聲明將推斷,對於方法的類型參數應與Class<Override>
被替換,即我們不得不在這種形式的方法的版本:
public List<Class<Override>> asList(Class<Override> ... elems)
但是,如果明確設置該方法的類型參數
List<Class<? extends Annotation>> l =
Arrays.<Class<? extends Annotation>>asList(Override.class);
那麼編譯器會真正知道什麼類型的參數必須與被替代之後,.asList()
方法的版本將是:
public List<? extends Annotation> asList(Class<? extends Annotation> ... elems)
現在,這將編譯很好,因爲Class<? extends Annotation>
兼容到Class<Override>
。在Java8中,類型推斷功能得到了進一步改進,因此您不必爲.asList()
方法明確設置類型參數。
然而,更有趣的問題去
爲什麼List<Class<Override>>
是不兼容List<Class<? extends Annotation>>
?
的java.lang.Class
是final
之一,這將有助於回答以下兩個問題,結合其將回答上述問題。:)
所以,
- 什麼是一個
List<Class<Override>>
是什麼意思?
List<Class<Override>>
意味着我們只能添加Class<Override>
的實例,而沒有其他任何內容添加到列表中。這很好,知道我們甚至不能添加Class<Override>
子類,因爲Class
類型是final
。
List<Class<? extends Annotation>>
是什麼意思?
這種類型的List
代表的類別列表的整體家庭,所有這一切都是Annotation
型,這意味着我們能夠成功地添加任何註釋類型(例如,SuppressWarnings.class
,Override.class
的子類,Documented.class
等)到列表中。
讓我們假設下面的例子實際上是正確的:
List<Class<Override>> overrides = Arrays.asList(Override.class);
List<Class<? extends Annotation>> annotations = new ArrayList<>();
annotations = overrides;
annotations.add(SuppressWarnings.class); //HUGE PROBLEM
annotations.add(Documented.class); //ANOTHER HUGE PROBLEM
兩個巨大的問題來自於一個事實,即我們正在努力一些非Override
實例添加到overrides
,這是非常錯誤的。
我們有足夠智能的編譯器,可以實際檢測到這些可能的問題,並且拋出編譯時錯誤是阻止我們這樣做的方式。
更多信息:
@kocko你使用了什麼java?我有jdk1.7_079,這裏有一個截圖https://www.dropbox.com/s/p6gybp1jct19ehg/generics.jpg – AdamSkywalker
我玩過這個,我想我找到了原因。我會在一段時間後寫一個答案。 –
從測試中,看起來像在Java 7中,您需要參數化靜態調用'Arrays。> asList(Override.class);'。對於Java 8,我不需要 –