2012-01-23 38 views
4

当我投来E[](类参数),它需要我补充爪哇 - 铸造到E []

@SuppressWarnings("unchecked") 

例如:

E[] anArray = (E[]) new Object[10]; 

我应该做不同的东西,还是应该是这样?

感谢

+0

@Mehrdad为什么要使用C#? – Stripies

+0

哈哈这是一个笑话,旨在解决这个问题(因为'新T []'完全可以在C#中)...并不意味着你认真对待它。:) – Mehrdad

+0

@Mehrdad我想通了,但我不喜欢C#,因为只能在Windows上使用它,但那不是重点。 – Stripies

回答

4

这是正确的。想象一下:

Object[] o = new Object[10]; 
o[0] = new A(); // A is not a subclass of E 
E[] e = o; // Now you have broken the type system: e[0] references something that is not an E. 

它的工作方式,你必须显式强制转换,以便让编译器忽略这种可能性。

2

它应该做的事情,因为那type erasure

为了避免以抑制警告,你能做的唯一的事情就是用List<E>(或类似Collection)。

+0

@Downvoter为什么? – Jeffrey

+0

据我所知,类型删除不适用于数组。请参阅http://java.sun.com/docs/books/jls/third_edition/html/arrays.html#10.8 – gpeche

+0

另请参阅http://docs.oracle.com/javase/7/docs/api/java/lang /Class.html#getComponentType%28%29。这种类型的擦除不可能。 – gpeche

2

是的,你应该做的是这样,因为我们不能初始化泛型的数组是这样的:

E[] array = new E[10]; // Compile error 

你真的这样做,你写的。我无法知道。


另一种方法是使用对象数组(而不是E)。你可以看到,在Java API开发人员做的也是这样的ArrayList类中:

/** 
* The array buffer into which the elements of the ArrayList are stored. 
* The capacity of the ArrayList is the length of this array buffer. 
*/ 
private transient Object[] elementData; 

,他们根本初始化数组是这样的:

elementData = new Object[size]; 

而且无处不在,他们使用它,他们投的阵列内容:

/** 
* Returns the element at the specified position in this list. 
* 
* @param index index of the element to return 
* @return the element at the specified position in this list 
* @throws IndexOutOfBoundsException {@inheritDoc} 
*/ 
public E get(int index) { 
    RangeCheck(index); 

    return (E) elementData[index]; 
} 

我真的不知道,但我认为第一种方法更快,因为在运行时不需要铸造。我想,Java VM会花费一些时间来铸造它。我为什么这么想?正因为如此,在运行时提供了一个错误:

Integer i = new Integer(34); 
Object o = i; 
String s = (String) o; // Runtime error 

因此,这意味着虚拟机真正检验它是否一个字符串。但事实上,编译器类型擦除让我觉得它没有任何区别。有人可以澄清吗?

+0

*声明一个泛型类型的数组不是问题。 'E []数组;'完全没问题。 –

+0

@ TomHawtin-tackline:好的,我明白了,我将编辑:D –

+0

运行时迟早会执行一个运行时类,并在适当的时候抛出ClassCastException。这不是C/C++世界及其未定义的行为。 – gpeche

3

您应该阅读Effective Java书。总之,不可能确切知道你的正确行为方式是因为我们不知道你在做什么,但通常你不应该压制这个警告。所以最有可能的解决方案是使用类型安全的泛型集合而不是数组。

+0

使用'ArrayList'作为例子,它抑制了这个警告,那么在数组上使用'ArrayList'会怎样? – Stripies

+0

看@gpeche说什么。数组不是类型安全的。这只是泛型的工作方式 - 编译器不能确保你正确地处理它们。当使用泛型ArrayList <>(而不是未经检查的ArrayList!)时,您将停留在泛型类型的擦除世界中,编译器仍然可以跟踪所有类型。 –

+0

但'ArrayList <>'也使用不安全的方法。下面是从'的ArrayList <>' @SuppressWarnings( “未登记”) ÈelementData中(INT指数){ 返回(E)elementData中[索引]的方法; } – Stripies