通用列表数组
我正在使用泛型和数组,似乎下面的代码编译得很好,
ArrayList<Key> a = new ArrayList<Key>();
但是编译器抱怨这个,
ArrayList<Key>[] a = new ArrayList<Key>[10];
通过阅读 stackoverflow 中的帖子,我有点明白这是由于类型擦除造成的,我可以通过使用来修复它,
ArrayList<Key>[] a = (ArrayList<Key> []) new ArrayList[10];
或者list of list
ArrayList<ArrayList<Key>> b = new ArrayList<ArrayList<Key>>();
但我无法弄清楚幕后的原因。特别是,为什么第二个是非法的,因为第一个是完全可以的。以及为什么编译器不会抱怨列表的列表。
I am playing with Generic and arrays, it seems the following code compiles fine,
ArrayList<Key> a = new ArrayList<Key>();
But the compiler complains about this one,
ArrayList<Key>[] a = new ArrayList<Key>[10];
By reading post in stackoverflow, I sort of understand that this is due to Type Erasure and I can fix it by using,
ArrayList<Key>[] a = (ArrayList<Key> []) new ArrayList[10];
or list of list
ArrayList<ArrayList<Key>> b = new ArrayList<ArrayList<Key>>();
But I can't figure out the reason behind the scene. Especially, why the second one is illegal given the first one is perfectly OK. And why the compiler does not complain about the list of list.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您不能拥有数组,因为数组需要原始类型。您在第二个实例中对其进行类型转换,这使其适合定义的类型,因此是合法的(但是,它不可能推断)。列表的列表是合法的,因为
ArrayList
不是数组。阅读官方教程中的第 7.3 章(第 15 页)了解更多信息有关于此的详细信息。
教程接着说以下内容:
You can't have an array, because an array requires a raw type. You typecast it in the second instance, which makes it fit the defined type, and is therefore legal (however, this is impossible for it to infer). The list of list is legal as
ArrayList
isn't an array.Read chapter 7.3 (page 15) in the official tutorial for more details on this.
The tutorial then goes on to say the following:
数组是穷人的泛型;对于真正的泛型,人们应该避免使用数组,尽管并不总是可行。
数组是协变的,泛型是不变的;与擦除相结合,事情就不太适合,正如克里斯回答中的例子所示。
不过我认为可以放宽规范以允许创建通用数组 - 那里确实没有问题。当上施法阵时危险就来了;此时编译器警告就足够了。
实际上Java确实为可变参数方法创建了泛型数组,所以这有点虚伪。
以下是利用这一事实的实用方法
Array was poor man's generics; with real generics, one should avoid arrays, though not always possible.
Arrays are covariant, generics are invariant; combined with erasure, things just don't fit very well, as illustrated by the example in Chris's answer.
However I think it is possible to relax the spec to allow generic array creation - there's really no problem there. The danger comes when up casting the array; a compiler warning at that point is enough.
Actually Java does create generic arrays for vararg methods, so it's a little hypocritical.
Here are utility methods taking advantage of that fact
我自己也有一个类似的问题 - FWIW,我发现答案没有说服力。最详细答案(参考pdf参考)的相关部分是这样的:
,因为我可以将 List[] 转换为 Object[],然后将不正确的内容塞入 Object[],然后通过强制转换的引用从 List 引用中错误地引用,这是不好的/不允许?但只有新的?
对我来说,仍然有点模糊的是,用 new 声明它比用法或多或少是一个问题,仍然交叉着眼睛盯着它,希望它能开始有意义,或者至少解决为一个漂亮的 3D 图像。
I had a similar question myself - FWIW, I didn't find the answers persuasive. The pertinent section from the most detailed answer (referring to the pdf reference) is this:
So because I can cat the List[] to Object[], then shove something incorrect into the Object[], then refer to incorrectly from the List reference, through the casted ref, this is bad/disallowed? But only with new?
It's still more than a bit obscure to me how declaring this with new is any more or less of a problem than the usage, still crossing my eyes staring at it in the hope that it will start to make sense, or at least resolve into a nice 3d image.
创建泛型数组不是类型安全的(请参阅 Joshua Bloch 的《Effective Java - 第二版》中的“条目 25:优先选择列表而不是数组”)。
使用:
或者使用 Java SE 7:
Creating generic arrays isn't type-safe (see "Item 25: Prefer lists to arrays" of "Effective Java - second edition" by Joshua Bloch).
Use:
Or with Java SE 7:
这些数组允许逃避类型检查(如克里斯的回答所示)。因此,您的代码可以通过所有编译器检查(编译器不会发出“未经检查”的警告),但在运行时会失败并出现 ClassCastException。
禁止这种构造会给开发人员带来问题,因此确实会出现警告。
The arrays allow to escape type checks (as illustrated in the Chris's answer). So, you could have a code which passes all compiler checks (no "unchecked" warnings from compiler), but fail at run time with ClassCastException.
Forbidding this construction raises the problem for a developer, so warnings do appear.