2014-09-04 158 views
1

我遇到了錯誤,我認爲會是一個直截了當的演繹,其中一個使用泛型的方法指定一個泛型類的一個版本作爲一個參數,第二個參數指定類型用於前一個參數的版本。Java泛型類型扣除錯誤

static class GenericClass<T0> 
{ 
    T0 getT() 
    { 
     return null; 
    } 

    static <T1> void func3(GenericClass<T1> a, T1 b) 
    { 

    } 
} 

void testcase(GenericClass<? extends Integer> a) 
{ 
    GenericClass.func3(a, a.getT()); 
} 

不幸的是它顯示爲錯誤:

"The method func3(GenericClass<T1>, T1) in the type GenericClass is not applicable for the arguments (GenericClass<capture#6-of ? extends Integer>, capture#7-of ? extends Integer)" 

但是這種變化FUNC3的頭作品。

static <T1> void func3(GenericClass<? extends T1> a, T1 b) 

對測試用例方法的標題進行了這種更改。

void testcase(GenericClass<Integer> a) 

即使測試用例頭不給該類的具體類型,該類指定返回類型將是一樣的泛型類型,爲什麼這個錯誤訊息建議他們是潛在的兩種不同類型的?

+1

我很確定Java從不跟蹤兩個'''類型是否相同'?',即使它可以。 – user2357112 2014-09-04 23:19:36

回答

1

這個例子並不明顯,因爲Integerfinal,所以讓我們舉一個例子,其中Parent有兩個子類,FooBar

? extends Parent是指Parent的某些特定亞型。因此可以使用GenericClass<Foo>GenericClass<Bar>,其中GenericClass<? extends Parent>預計。

這裏

static <T1> void func3(GenericClass<T1> a, T1 b) 

您擁有的泛型類型參數在兩個參數聲明中使用的通用方法。編譯器必須保證在方法調用期間提供的兩個參數中的類型都是正確的。

鑑於這種

GenericClass<? extends Parent> a = ...; 
GenericClass.func3(a, a.getT()); 

它沒有辦法做到這一點。您必須先了解Java不知道這兩個參數來自同一個來源。它看起來都是它們的類型。

第一個參數的類型爲GenericClass<? extends Parent>,而第二個參數的類型爲? extends Parent。考慮以下

GenericClass<? extends Parent> a = new GenericClass<Foo>(someFoo); 
GenericClass<? extends Parent> b = new GenericClass<Bar>(someBar); 
GenericClass.func3(a, b.get()); 

兩個參數有相同的編譯時類型以上的方法調用,但它更容易看到爲什麼它會失敗。它不能保證T將被綁定到兩個參數的相同類型。因此它必須失敗。

+0

啊,現在有道理 - 「Java不知道這兩個參數來自同一個來源」。因此,第二個參數的類型只是從get方法中獨立導出,然後將參數相互比較。謝謝。 – user2219808 2014-09-05 09:18:06