java 通用列表数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7810074/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Array of Generic List
提问by Hong
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,
通过阅读stackoverflow中的帖子,我有点明白这是由于类型擦除造成的,我可以使用以下方法修复它,
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.
但我无法弄清楚幕后的原因。特别是,为什么第二个是非法的,因为第一个是完全可以的。以及为什么编译器不抱怨列表列表。
回答by Chris Dennett
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.
您不能拥有数组,因为数组需要原始类型。您在第二个实例中对它进行类型转换,这使其适合定义的类型,因此是合法的(但是,它无法推断)。list 的列表是合法的,因为ArrayList
它不是数组。
Read chapter 7.3 (page 15) in the official tutorialfor more details on this.
有关更多详细信息,请阅读官方教程中的第 7.3 章(第 15 页)。
The component type of an array object may not be a type variable or a parameterized type, unless it is an (unbounded) wildcard type.You can declare array types whose element type is a type variable or a parameterized type, but not array objects. This is annoying, to be sure. This restriction is necessary to avoid situations like:
List<String>[] lsa = new List<String>[10]; // not really allowed Object o = lsa; Object[] oa = (Object[]) o; List<Integer> li = new ArrayList<Integer>(); li.add(new Integer(3)); oa[1] = li; // unsound, but passes run time store check String s = lsa[1].get(0); // run-time error - ClassCastException
If arrays of parameterized type were allowed, the example above would compile without any unchecked warnings, and yet fail at run-time.
数组对象的组件类型不能是类型变量或参数化类型,除非它是(无界)通配符类型。您可以声明元素类型为类型变量或参数化类型的数组类型,但不能声明数组对象。这很烦人,这是肯定的。此限制是必要的,以避免出现以下情况:
List<String>[] lsa = new List<String>[10]; // not really allowed Object o = lsa; Object[] oa = (Object[]) o; List<Integer> li = new ArrayList<Integer>(); li.add(new Integer(3)); oa[1] = li; // unsound, but passes run time store check String s = lsa[1].get(0); // run-time error - ClassCastException
如果允许参数化类型的数组,则上面的示例将在没有任何未经检查的警告的情况下编译,但在运行时会失败。
The tutorial then goes on to say the following:
然后教程继续说以下内容:
Since type variables don't exist at run time, there is no way to determine what the actual array type would be. The way to work around these kinds of limitations is to use class literals as run time type tokens
由于类型变量在运行时不存在,因此无法确定实际的数组类型。解决这些限制的方法是使用类文字作为运行时类型标记
回答by irreputable
Array was poor man's generics; with real generics, one should avoid arrays, though not always possible.
Array 是穷人的泛型;对于真正的泛型,应该避免使用数组,尽管并非总是可行。
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.
数组是协变的,泛型是不变的;结合擦除,事情不太适合,如 Chris 回答中的示例所示。
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.
实际上Java确实为可变参数方法创建了泛型数组,所以有点虚伪。
Here are utility methods taking advantage of that fact
以下是利用这一事实的实用方法
@SafeVarargs
static <E> E[] arrayLiteral(E... array)
{
return array;
}
@SafeVarargs
static <E> E[] newArray(int length, E... array)
{
return Arrays.copyOf(array, length);
}
// usage
List<String>[] array1 = arrayLiteral(list, list);
List<String>[] array2 = newArray(10);
回答by Steve B.
I had a similar questionmyself - FWIW, I didn't find the answers persuasive. The pertinent section from the most detailed answer (referring to the pdf reference) is this:
我自己也有类似的问题- FWIW,我没有找到有说服力的答案。最详细答案中的相关部分(参考 pdf 参考)是这样的:
The component type of an array object may not be a type variable or a parameterized type, unless it is an (unbounded) wildcard type.You can declare array types whose element type is a type variable or a parameterized type, but not array objects. This is annoying, to be sure. This restriction is necessary to avoid situations like
数组对象的组件类型不能是类型变量或参数化类型,除非它是(无界)通配符类型。您可以声明元素类型为类型变量或参数化类型的数组类型,但不能声明数组对象。这很烦人,这是肯定的。此限制是必要的,以避免出现以下情况
List<String>[] lsa = new List<String>[10]; // not really allowed
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li; // unsound, but passes run time store check
String s = lsa[1].get(0); // run-time error - ClassCastException
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?
因此,因为我可以将 List[] 转换为 Object[],然后将一些不正确的东西推入 Object[],然后从 List 引用中错误地引用,通过强制转换的 ref,这是错误的/不允许的吗?但只有新的?
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.
对我来说,用 new 声明这一点比使用更或多或少是一个问题,仍然有点模糊,我仍然盯着它盯着它,希望它开始变得有意义,或者至少解决成一个漂亮的 3d 图像。
回答by Puce
Creating generic arrays isn't type-safe (see "Item 25: Prefer lists to arrays" of "Effective Java - second edition" by Joshua Bloch).
创建泛型数组不是类型安全的(参见 Joshua Bloch 的“Effective Java - second edition”的“Item 25: Prefer lists to arrays”)。
Use:
利用:
List<List<Key>> b = new ArrayList<List<Key>>(10);
Or with Java SE 7:
或者使用 Java SE 7:
List<List<Key>> b = new ArrayList<>(10);
回答by kan
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.
数组允许转义类型检查(如 Chris 的回答所示)。因此,您可能有一个通过所有编译器检查的代码(没有来自编译器的“未检查”警告),但在运行时因 ClassCastException 而失败。禁止这种构造会给开发人员带来问题,因此确实会出现警告。