2012-11-19 87 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中结束。