2012-11-19 88 views
2

我有一個擴展Paint的參數的泛型類。我真的不明白爲什麼我應該在第一個構造函數中手動將它投射到T上。我究竟做錯了什麼?或者當編譯器無法確定自己的安全模式時,情況就是如此?如何手動投射泛型類型?

public class XYPlot <T extends Paint> extends AbsPlot implements XYChartElement { 
public XYPlot(AbsSeries series){ 
    setUp(series, (T) new Paint(DEFAULT_PAINT));//TODO 
} 

public XYPlot(AbsSeries series, T paint){ 
    setUp(series, paint); 
} 

private void setUp(AbsSeries series, T paint){ 
    if(series == null) throw new NullPointerException("Series is null"); 
    setSeries(series); 
    setPaint(paint); 
} 

回答

5

我真的不明白爲什麼我要在第一個構造函數手動將其丟至T。

你不應該 - 首先你不應該創建一個只有Paint的實例。那Paint不會T的一個實例,除非T正好是Paint。一個只適用於單一類型參數的泛型類首先不應該是泛型的。

如果你需要的T建設一個實例,你會要麼需要調用者傳遞一箇中,採取Class<T>,這樣就可以使用反射看看通過構造函數,並調用合適的一個。

讓我們看看你在做什麼,一個簡單的版本希望你就會明白爲什麼這是錯的:

public class Wrapper<T extends Object> 
{ 
    private final T value; 

    public Wrapper() 
    { 
     value = (T) new Object(); 
    } 

    public T getValue() 
    { 
     return value; 
    } 
} 

這裏,我們使用Object代替Paint - 但除此之外,它基本上是相似的。

現在,如果我們把它稱爲:

Wrapper<String> wrapper = new Wrapper<String>(); 
String text = wrapper.getValue(); 

...你會想到做什麼?

基本上不清楚爲什麼你在第一個地方使你的類通用 - 但你採取的方法本質上是有缺陷的。

+0

好吧,現在我明白了這個問題。所以我決定讓子類創建像這樣的默認值。這是一個好主意嗎? '公共抽象類包裝器 {0}私有final T值; () public wrapper() { value = getDefaultValue(); () } public abstract T getDefaultValue() public T getValue() { return value; } }' –

+0

@KorniltsevAnatoly:好吧,沒關係,只要你有每個類型參數的子類...否則它變得同樣棘手。如果你正在創建子類,爲什麼不讓子類構造函數將值傳遞給超類構造函數,而不是使用虛方法? –

+0

那更好! –

0
setUp(series, (T) new Paint(DEFAULT_PAINT)); 

這只是安全的,如果你對T實際參數是Paint本身。如果類型參數是Paint的某個子類,那最終會在CCE中結束。