2012-11-21 161 views
2

让我们说,我想通过默认的构造函数创建泛型类型

public class A <E extends Comparable<? super E>> implements B<E> 
{ 
    private E[] myArray; 


    public A() 
    { 
     myArray = (E[]) new Object[5]; 
    }  

} 

这是做的正确的方式创建长度为5的数组的数组?我很困惑,我是否需要在[]之前 状态“Comparable”。所以

private Comparable[] myArray; 
+0

恕我直言,是的,这是正确的。 – jlordo

+0

不必声明“Comparable”,因为编译器强制'E'成为'Comaparable'。 – jlordo

+0

非常感谢! – hibc

回答

2

与您发布的代码的问题是,E[]擦除是Comparable[](因为E的上限是Comparable),因此将其实际类型为Object[]的对象转换为Comparable[]将失败。

你可以简单地将其更改为以下,也不会抛出异常:

public class A <E extends Comparable<? super E>> implements B<E> 
{ 
    private E[] myArray; 


    public A() 
    { 
     myArray = (E[]) new Comparable[5]; 
    }  

} 

但是,这里更细微之处:myArray是不是真的E[]类型。在课堂上,E[]被擦除到Comparable[],所以没关系。但是你必须确保永远不要在班级之外暴露myArray。由于它是私人的,你只需确保没有方法返回它或什么。

做这种方式,保持E[]myArray,在使用Comparable[]的Jatin的答案的好处是,你不必投每次你得到的东西出来的时候,这样的代码是更好的。

+0

中非常感谢!!! 1 – hibc

1

由于@Jatin所指出的,因此当你施放ObjectComparable,因为它是为Comparable超,正因为如此,不能被强制转换为子类型得到一个运行时异常。

我会建议你使用ArrayList而是如果可能的话:

例如

public class A <E extends Comparable<? super E>> implements B<E> { 
    private List<E> myArray; 

    public A() { 
     myArray = new ArrayList<E>(); 
    }  
} 
+1

为什么在大小不变时使用'ArrayList'? – jlordo

+0

'ArrayList'具有动态大小 - 很少需要恒定大小的数组。动态调整数据结构可能会提供更大的灵活性。 – wulfgarpro

+0

非常感谢! – hibc

4

没有。它会在运行时抛出ClassCastException

让我们看看原因。由于<E extends Comparable<? super E>>,一旦所有的泛型类型被编译器擦除,E将全部替换为Comparable

所以在你的构造函数,这是在运行时发生的主要:

myArray = new Comparable[5]; 

哪项是错误的,因此除外。

这将曾与class A <E> implements B<E>

工作因此,解决办法是:

class A <E extends Comparable<? super E>> implements B<E>{ 
    Comparable[] array; 
    public A(){ 
    array = new Comparable[5]; 
    } 
    @SuppressWarnings("unchecked") 
    E get(int x) 
    { 
    return (E) array[x]; 
    } 
    void add(E b){ 
    //for now 
    array[0] = b; 
    } 
+0

你是对的。 – wulfgarpro

+0

myArray = new Comparable [5]会这样工作吗? – hibc

+0

是的。但它会引发编译时警告。因为类型没有解释为新的可比较的 [5]。而且你不能放置类型,因为它是非法的。为什么可以在http://jatinpuri.com找到 – Jatin