2016-11-30 147 views
0

下列類型不產生任何編譯器警告:泛型類型參數給出了錯誤,但通配符類型參數不

public abstract Class<? extends BaseType> getSubclassType(); 
@Override 
    public Class<SubType> getSubclassType() { 
     return SubType.class; 
    } 

下面的具體方法產生一個unchecked投編譯器警告:

public abstract <T extends BaseType> Class<T> getSubclassType(); 

    @Override 
    public <T extends BaseType> Class<T> getSubclassType() { 
     return (Class<T>) SubType.class; 
    } 

有沒有辦法用泛型類型參數(在基類中)定義方法,並在子類中返回適當的具體類型而不生成編譯器警告?很明顯,我上面給出的兩個例子都可以正常工作,我只想知道是否有更正確的方法來定義方法。注:我知道我可以做到以下幾點:

public abstract class BaseClass <T extends BaseType> 
public abstract Class<T> getSubclassType(); 

我想知道如果有一種方法來定義方法頭本身,具有泛型類型,而不定義它的類。而且,我很好奇爲什麼通配符聲明不給與警告,而是「等價的」泛型聲明。

+0

在通配符示例中,「SubType.class」必須是「類」類型。然而,在泛型中,程序沒有辦法隱式知道「SubType.class」是否真的擴展了'BaseType',所以它會給出警告。至於避免這種情況的方法,我想不出來。 – Mat

回答

1

這兩者是非常不同的。

在第一個中,調用者不知道返回的Class的類型參數是什麼。調用者無法對該類型參數進行任何假設,除非它擴展爲BaseType。該方法可以選擇返回一個Class,其類型參數是它想要的任何子類型BaseType,調用者不知道。

在第二種情況下,該方法是一種通用方法,並且T是該方法的類型變量。這意味着來電者可以選擇T以達到任何想要的效果,並希望該方法可以神奇地與T一起使用。值得注意的是,該方法沒有收到任何參數,這意味着該方法在運行時沒有任何關於什麼的信息,並且必須知道如何返回Class<T>。顯然,這是不可能的,除非它總是返回null

+0

是不是兩個例子擦除到 公共類 getSubclassType(){ return(Class )SubType.class; } – KyleM

+0

@KyleM:兩者的擦除都相同:'public class getSubclassType(){ return SubType.class; }',但這是無關緊要的。調用者可以在每種類型簽名的泛型中做的事情是非常不同的。 – newacct

+0

實際上是完美的感覺。換句話說(就我的理解而言,你的解釋很棒)......在第二個例子中,調用者可以指定他們想要的任何類型,並期望該方法返回該類型。然而,這顯然是不可能的,因爲它在運行時沒有那種類型的信息。相反,在我的第一個例子中,調用者只知道返回的類型擴展了BaseType;並且不能對該類型做出額外的假設。 – KyleM