2014-10-08 65 views
0

我試圖從我的主要得富():無法瞭解java通配符

<T extends Main> T foo() 
{ 
    return this; // "this" it is a instance of Main 
} 

而且使用它

Main m = new Main(); 
Main m2 = m.foo(); 

而且我得到了一個錯誤:「不兼容類型所需ŧ ,在方法foo()中找到Main「。
我知道我可以用這個:

<T extends Main> T foo2(T a) { 
    return a; 
} 

並使用它:

Main m = new Main(); 
Main m3 = m.foo2(m); 

,它工作正常。但我不明白,爲什麼我不能使用第一種方法?因爲this絕對是Main的實例擴展。

回答

8

如果您在類型定義<T extends Main> T foo();Main你不能只返回this,因爲T可能是Main一個亞型,這當然Main不是。所以如果你有MainSubType m = new Main().foo();編譯器想要誘導T作爲MainSubType但面對它只是類型Main,所以你必須解析它艱難的方式,我不能在這裏推薦,但這就是你如何去<T extends Main> T foo(){return (T) this}。如果你這樣做,你應該確實能夠編譯其餘的。

如果它不適用於foo()中的(T)-cast,則需要提供更多上下文/代碼。

2

作爲user2504380 already pointed out:如果這是可能的,你可以默默地「上傳」任何Main任何Main的子類。

但是,你可能根本不需要這個類型參數(至少,我無法想象它可能有意義的情況)。如果您的類看起來是這樣的:

class Main { 
    Main getIt() { 
     return this; 
    } 
} 

,那麼你可以創建Main一個子類,並且由於在Java中covariance,重寫返回的Main

class SubMain { 

    // Overriding with a more specific return type: 
    @Override 
    SubMain getIt() { 
     return this; 
    } 
} 

此相應的亞型的方法意味着該方法的返回類型取決於您正在調用該方法的參考類型:

Main main = new Main(); 
SubMain subMain = new SubMain(); 

Main m0 = main.getIt(); 
Main m1 = subMain.getIt(); 

// This does not work 
//SubMain s0 = main.getIt(); 

// But this works: The instance IS a SubMain, and returns a SubMain: 
SubMain s1 = subMain.getIt(); 

在涉及自引用泛型類型的更復雜場景中,您可能會使用getThis trick

+0

謝謝你的回答,但我想了解Java協方差。 – Alexmelyon 2014-10-08 12:52:53

0

正如其他人已經指出,在

<T extends Main> 

編譯器的情況下不能可靠地判別T的類型,可以是主或子類主要的。由於這種不確定性,編譯器將不允許返回這個。如果使用T類型投影逆向類型,如

(T) this 

或者如果存在類型T的方法參數,則沒有不確定性。