2014-06-09 62 views
5

下面的語句:爲什麼不能分配I <?將Type>擴展爲<Type>?

URLClassLoader ucl = (URLClassLoader) ClassLoader.getSystemClassLoader(); 
Class<URLClassLoader> uclc = ucl.getClass(); 

失敗,錯誤:

Type mismatch: cannot convert from Class<capture#2-of ? extends URLClassLoader> to Class<URLClassLoader> 

爲什麼我需要打石膏,在這裏?

我發現了幾篇文章,解釋了爲什麼你不能做相反的事情(把T分配給a),但這是(明顯的)和理解的。

注:我在月食Luna下編碼,所以我不知道它是否是Luna Quirk,或者是否有我在泛型中不瞭解的東西。

回答

6

Covariance vs contravariance vs invariance

  • Class<? extends URLClassLoader>不變

結果,

Class<? extends URLClassLoader>不是Class<URLClassLoader>


的亞型在Java一個變量可以保存相同類型或亞型的實例的引用。

因此,

Class<URLClassLoader> uclc = ucl.getClass(); 

無效

在另一方面,

Class<? extends URLClassLoader> uclc = ucl.getClass(); 

有效

+1

你能eloborate爲什麼'類'(或'類')不是'類'亞型?我覺得是這樣的。 – skiwi

+0

@swiki:嘗試從收藏角度思考。你認爲List <?擴展Number>應該可以分配到列表?這將導致類型安全問題並且不被允許。雖然允許相反的分配。 –

+0

閱讀此奇妙的解釋:http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ503 –

1

Why can't assign I <? extends Type> to <Type>?

因爲實際上<? extends Type><Type>的超類型!讓我們按照規範。

4.10.2 Subtyping among Class and Interface Types

Given a generic type declaration C<F1,...,Fn>, the direct supertypes of the parameterized type C<T1,...,Tn> are all of the following:

  • C<S1,...,Sn>, where Si contains Ti.

4.5.1. Type Arguments of Parameterized Types

A type argument T1 is said to contain another type argument T2, written T2 <= T1, if the set of types denoted by T2 is provably a subset of the set of types denoted by T1 under the reflexive and transitive closure of the following rules:

  • T <= ? extends T

因此,我們知道,因爲? extends URLClassLoader包含URLClassLoaderClass<? extends URLClassLoader>Class<URLClassLoader>的超類型。

由於在assignment context內不允許narrowing reference conversion,因此會發生編譯錯誤。

還要注意的是,這意味着反向分配許可:

Class<URLClassLoader> concrete = URLClassLoader.class; 
Class<? extends URLClassLoader> wildcard = concrete; 
相關問題