2017-08-14 174 views
3

爲OCPJP 6考試做準備(這就是爲什麼我使用Java 1.6編譯器)我注意到了我對Java泛型的一些不清楚。 考慮下面的代碼:Java泛型類型參數不在其範圍內

class A<K extends Number> { 

    public <V> V useMe1(A<? super V> a) { // OK 
     return null; 
    } 

    public <V> V useMe2(A<? extends V> a) { // OK 
     return null; 
    } 

    public <V> V useMe3(A<V> a) { // ERROR, but why, since 2 above were ok 
     return null; 
    } 

} 

當我嘗試編譯代碼(1.6編譯器),我得到的錯誤:

type parameter V is not within its bound

儘管上面的代碼的unusability,我不知道爲什麼編譯器認爲類型<? super V><? extends V>與綁定的類類型匹配,但<V>不是(因爲V與這兩個邊界匹配)。

我不打算修改該代碼,我想了解它。該代碼取自示例OCPJP 6考試問題,詢問「哪一行將編譯?」

+1

'useMe2'不能用Java 8編譯。 – assylias

+0

第二個不能編譯:/ –

回答

1

第三個是useMe3,因爲V由於其聲明<V>缺少界限而不能保證爲extend Number。並且由於參數被聲明爲A<V>,所以沒有scape,V必須擴展爲Number,並且Java語言要求程序員在這種情況下明確聲明。

這實際上是簡單的,也許不太明顯,爲什麼其他兩個可能工作。 通過在他們的參數類型定義使用?你給的那勢必會與extend Number兼容的可能性,即使V本身沒有被有關任何特定的綁定限制爲Number一個修道院。

您必須注意,extend Number不會再影響V,而是不會影響?無論如何。把它的另一種方式,有一個由?和必extend Number和對方法useMe1最重要的是代表一個未知的類,例如,它必須是V超級哪裏V將被調用的代碼來確定方法。

這在useMe2的情況下可能更有趣,其中V實際上可以與Number完全無關。例如:

interface FooInterface { ... } 
class MyNumber extends Number implements FooInterface { ... } 

A<?> subject = ...; 
A<MyNumber> param = ...; 
FooInterface foo = subject.useMe2(param); 

在上面的useMe2電話,VFooInterface有無關Number,而在這種情況下MyNumber?MyNumber受限於A類型參數綁定擴展爲Number並且由參數的類型參數定義useMe2擴展爲FooInterface但是V本身完全不受限制。