I must be confused here.
我一定很困惑。
I read everywhere that in generics arrays of parametrized types are illegal.
我到处都读到,在泛型数组中参数化类型是非法的。
Example from AngelikaLanger:
从AngelikaLanger示例:
static void test() {
Pair<Integer,Integer>[] intPairArr = new Pair<Integer,Integer>[10] ; // error
addElements(intPairArr);
Pair<Integer,Integer> pair = intPairArr[1];
Integer i = pair.getFirst();
pair.setSecond(i);
}
Quote from Langer (but everywhere else I read it says the same thing):
引用Langer的话(但是我在其他地方读到的都是一样的):
The compiler prohibits creation of arrays whose component type is a concrete parameterized type, like Pair in our example. We discussed in the preceding entry why is it reasonable that the compiler qualifies a Pair[] as illegal.
编译器禁止创建组件类型为具体参数化类型的数组,如我们示例中的Pair。我们在前面的条目中讨论了为什么编译器将一对[]限定为非法是合理的。
So far ok.
到目前为止好了。
But in my code here:
但在我的代码中:
private MyEntry<E> [] elements = (MyEntry<E>[])new Object[capacity];
I do exactly that, it compiles fine (I use eclipse) but get a class cast exception error (Object can not be cast to MyEntry):
我确实做到了,它编译了fine(我使用eclipse),但是得到了一个类cast exception错误(对象不能被转换为MyEntry):
My question is, why does this line compiles in the first place?
我的问题是,为什么这一行首先编译?
I thought that this instantiation is disallowed by the compiler.
我认为编译器不允许这种实例化。
What I am doing wrong/differerent here?
我在这里做错什么/有什么不同?
UPDATE:
更新:
On the same page, why am I able to succesfully do:
在同一页上,为什么我能成功地做到:
List<E> elements[] = (List<E>[])new LinkedList[capacity];
and have no runtime exceptions?
没有运行时异常吗?
UPDATE:
更新:
Everywhere I have read (mentioned Langer since she's quoted often) it says that this declaration (arrays of parametrized types) is disallowed by compiler.
I can understand what happens after that.
I can't understand why the compiler doesn't report an error.
I am not judging, I am saying everywhere I read, it says this does not compile.
Am I missreading something?
我读过的每一个地方(因为Langer经常引用她)都说编译器不允许这个声明(参数化类型的数组)。我能理解那之后会发生什么。我不明白为什么编译器不报告错误。我不是在评判,我说我读到的每一个地方,都说这不是汇编。我missreading吗?
UPDATE: I saw some comments related to the missing parameter in the new
part.
This also has no issue:
更新:我看到了一些关于新部件中丢失参数的评论。这也没有问题:
List<Entry<KeyType, ValueType>> table[] = (List<Entry<KeyType, ValueType>>[])new LinkedList[capacity];
3 个解决方案
#1
2
In your first example, there's no problem with the instantiation - here's exactly what you're creating:
在您的第一个示例中,实例化没有问题——以下就是您正在创建的:
new Object[capacity]
Perfectly legal. You do however get a runtime exception when you attempt to cast, because an array of Object
is not an array of MyEntry<E>
. You might have a point that the cast or declaration could be rejected by the compiler, if these generically-parameterised arrays can't exist, though this depends what order erasure kicks in. In any case, the instantiation itself is fine.
完全合法的。但是,当您尝试强制转换时,您会得到一个运行时异常,因为对象数组不是MyEntry
In the second example, you're creating a non-generic array of LinkedList
. You then assign it to a genericised reference, which at runtime will have been erased to just a List[]
. This works fine (because rightly or wrongly, arrays are covariant).
在第二个示例中,您正在创建一个非通用的LinkedList数组。然后您将它分配给一个泛型引用,在运行时它将被删除为一个列表[]。这样做很好(因为无论正确与否,数组都是协变的)。
I'm not sure why you were expecting a runtime exception; it's not much different to calling, say
我不知道您为什么期望运行时异常;这和打电话没什么区别
List<E> = new LinkedList();
You would get some unchecked warnings, but nothing that would stop the code compiling or running.
您将得到一些未检查的警告,但是没有什么会阻止代码编译或运行。
#2
1
You have completely misunderstood whatever you have read. There is absolutely nothing wrong with having the type that is an array of a parameterized type: MyEntry<E>[]
or HashMap<String,Integer>[][]
or whatever. You can have variables of such types all you want, and use them anywhere a type can be used.
无论你读什么,你都完全误解了。拥有参数化类型的数组类型绝对没有问题:MyEntry
However, with array creation, you cannot do something like new MyEntry<E>[...]
. It is not allowed by the language (for type safety reasons we will not go into here), so it is a compile error.
但是,对于数组创建,您不能执行类似于new MyEntry
The best solution is either new MyEntry[]
(array of raw type) or new MyEntry<?>[]
(array of wildcard type); either one is allowed by the language. Both of them will require you to do an explicit cast back to MyEntry<E>[]
.
最好的解决方案是新的MyEntry[](原始类型数组)或新的MyEntry
[](通配符类型数组);任何一种语言都是允许的。这两个都需要您对MyEntry
Since you ask about your code examples, your first example is syntactically correct (there is nothing wrong with new Object[...]
, and it is syntactically okay to cast to MyEntry<E>[]
), so there is no compile error. However, the runtime check of the cast fails at runtime, because the object's actual type Object[]
is not a subtype of MyEntry[]
.
既然您要询问您的代码示例,那么您的第一个示例在语法上是正确的(new Object[…],从语法上来说,可以将它转换为MyEntry
The second code example is also syntactically correct, and plus the runtime check of the cast succeeds (LinkedList[]
is a subtype of List[]
).
第二个代码示例也是语法正确的,并且加上cast的运行时检查(LinkedList[]是List[]的子类型)。
#3
1
Because LinkedList
is an instance of List
. But Object
is NOT an instance of MyEntry
. Also compiler don't check can one object be cast to another or not. Because it is runtime operation.
因为LinkedList是List的一个实例。但对象不是MyEntry的实例。编译器也不检查一个对象是否可以转换成另一个对象。因为它是运行时操作。
You should use:
你应该使用:
private MyEntry<E> [] elements = new MyEntry [capacity];
Or:
或者:
class SomeOtherEntry extends MyEntry {}
private MyEntry<E> [] elements = new SomeOtherEntry [capacity];
But not:
而不是:
class SomeOtherEntry extends MyEntry {}
private SomeOtherEntry <E> [] elements = new MyEntry [capacity];
UPDATE:
更新:
List<Entry<KeyType, ValueType>> [] table = (List<Entry<KeyType,ValueType>> []) new Linked[capacity];
#1
2
In your first example, there's no problem with the instantiation - here's exactly what you're creating:
在您的第一个示例中,实例化没有问题——以下就是您正在创建的:
new Object[capacity]
Perfectly legal. You do however get a runtime exception when you attempt to cast, because an array of Object
is not an array of MyEntry<E>
. You might have a point that the cast or declaration could be rejected by the compiler, if these generically-parameterised arrays can't exist, though this depends what order erasure kicks in. In any case, the instantiation itself is fine.
完全合法的。但是,当您尝试强制转换时,您会得到一个运行时异常,因为对象数组不是MyEntry
In the second example, you're creating a non-generic array of LinkedList
. You then assign it to a genericised reference, which at runtime will have been erased to just a List[]
. This works fine (because rightly or wrongly, arrays are covariant).
在第二个示例中,您正在创建一个非通用的LinkedList数组。然后您将它分配给一个泛型引用,在运行时它将被删除为一个列表[]。这样做很好(因为无论正确与否,数组都是协变的)。
I'm not sure why you were expecting a runtime exception; it's not much different to calling, say
我不知道您为什么期望运行时异常;这和打电话没什么区别
List<E> = new LinkedList();
You would get some unchecked warnings, but nothing that would stop the code compiling or running.
您将得到一些未检查的警告,但是没有什么会阻止代码编译或运行。
#2
1
You have completely misunderstood whatever you have read. There is absolutely nothing wrong with having the type that is an array of a parameterized type: MyEntry<E>[]
or HashMap<String,Integer>[][]
or whatever. You can have variables of such types all you want, and use them anywhere a type can be used.
无论你读什么,你都完全误解了。拥有参数化类型的数组类型绝对没有问题:MyEntry
However, with array creation, you cannot do something like new MyEntry<E>[...]
. It is not allowed by the language (for type safety reasons we will not go into here), so it is a compile error.
但是,对于数组创建,您不能执行类似于new MyEntry
The best solution is either new MyEntry[]
(array of raw type) or new MyEntry<?>[]
(array of wildcard type); either one is allowed by the language. Both of them will require you to do an explicit cast back to MyEntry<E>[]
.
最好的解决方案是新的MyEntry[](原始类型数组)或新的MyEntry
[](通配符类型数组);任何一种语言都是允许的。这两个都需要您对MyEntry
Since you ask about your code examples, your first example is syntactically correct (there is nothing wrong with new Object[...]
, and it is syntactically okay to cast to MyEntry<E>[]
), so there is no compile error. However, the runtime check of the cast fails at runtime, because the object's actual type Object[]
is not a subtype of MyEntry[]
.
既然您要询问您的代码示例,那么您的第一个示例在语法上是正确的(new Object[…],从语法上来说,可以将它转换为MyEntry
The second code example is also syntactically correct, and plus the runtime check of the cast succeeds (LinkedList[]
is a subtype of List[]
).
第二个代码示例也是语法正确的,并且加上cast的运行时检查(LinkedList[]是List[]的子类型)。
#3
1
Because LinkedList
is an instance of List
. But Object
is NOT an instance of MyEntry
. Also compiler don't check can one object be cast to another or not. Because it is runtime operation.
因为LinkedList是List的一个实例。但对象不是MyEntry的实例。编译器也不检查一个对象是否可以转换成另一个对象。因为它是运行时操作。
You should use:
你应该使用:
private MyEntry<E> [] elements = new MyEntry [capacity];
Or:
或者:
class SomeOtherEntry extends MyEntry {}
private MyEntry<E> [] elements = new SomeOtherEntry [capacity];
But not:
而不是:
class SomeOtherEntry extends MyEntry {}
private SomeOtherEntry <E> [] elements = new MyEntry [capacity];
UPDATE:
更新:
List<Entry<KeyType, ValueType>> [] table = (List<Entry<KeyType,ValueType>> []) new Linked[capacity];