在 Java 中创建一个数组来存储泛型类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16415255/
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
Creating an array to store generic types in Java
提问by Geek
Suppose I have to create an array which stores ArrayList's of Integers and the array size is 10.
假设我必须创建一个数组来存储 ArrayList 的整数,并且数组大小为 10。
The below code will do it:
下面的代码将做到这一点:
ArrayList<Integer>[] pl2 = new ArrayList[10];
Question 1:
问题 1:
In my opinion the more appropriate code would be
在我看来,更合适的代码是
ArrayList<Integer>[] pl2 = new ArrayList<Integer>[10];
Why does this not work?
为什么这不起作用?
Question 2:
问题2:
Both of the below compile
下面两个都编译
ArrayList<Integer>[] pl2 = new ArrayList[10];
ArrayList[] pl3 = new ArrayList[10];
ArrayList<Integer>[] pl2 = new ArrayList[10];
ArrayList[] pl3 = new ArrayList[10];
What is the difference as far as the reference declaration of pl2
and pl3
is concerned?
有什么区别尽可能的引用声明pl2
和pl3
关注?
采纳答案by Vladimir
Question 1:
问题 1:
Basically, this is forbidden by Java language. This is covered in Java Language Specification for generics.
基本上,这是 Java 语言所禁止的。泛型的 Java 语言规范中对此进行了介绍。
When you use
当你使用
ArrayList<Integer>[] pl2 = new ArrayList[10]; // warning
you get the compiler warning, because the following example will compile (generating warning for every line of code):
您会收到编译器警告,因为以下示例将编译(为每一行代码生成警告):
ArrayList wrongRawArrayList = new ArrayList(); // warning
wrongRawArrayList.add("string1"); // warning
wrongRawArrayList.add("string2"); // warning
pl2[0] = wrongRawArrayList; // warning
but now you array, that supposed to contain ArrayList
of Integer
, contains totally wrong ArrayList
of String
objects.
但是现在你的数组,应该包含ArrayList
of Integer
,包含完全错误ArrayList
的String
对象。
Question 2:
问题2:
As it was already answered, declaration of p12
provides you with compile time checking and frees you from using casting when getting items from your ArrayList
.
正如已经回答的那样,声明p12
为您提供了编译时检查,并使您在从ArrayList
.
Slightly modified previous example:
对前面的例子稍作修改:
ArrayList<Integer>[] pl2 = new ArrayList[10]; // warning
ArrayList<String> wrongArrayList = new ArrayList<String>(); // OK!
wrongArrayList.add("string1"); // OK!
wrongArrayList.add("string2"); // OK!
pl2[0] = wrongArrayList; // ERROR
Now, since you are using generics, this won't compile. But if you use
现在,由于您使用的是泛型,因此无法编译。但是如果你使用
ArrayList[] pl2 = new ArrayList[10];
you will get the same result as in the first example.
您将获得与第一个示例相同的结果。
回答by ltebean
The generic info only matters in compile time, it tells the compiler which type could be put into an array, in runtime, all the generic info will be erased, so what matters is how you declare the generic type.
泛型信息只在编译时重要,它告诉编译器可以将哪种类型放入数组,在运行时,所有泛型信息都将被删除,所以重要的是如何声明泛型类型。
Quoted from Think in Java:
引用自用 Java 思考:
it's not precisely correct to say that you cannot create arrays of generic types. True, the compiler won't let you instantiate an array of a generic type. However, it will let you create a reference to such an array. For example:
List<String>[] ls;
This passes through the compiler without complaint. And although you cannot create an actual array object that holds generics, you can create an array of the non-generified type and cast it:
//: arrays/ArrayOfGenerics.java // It is possible to create arrays of generics. import java.util.*; public class ArrayOfGenerics { @SuppressWarnings("unchecked") public static void main(String[] args) { List<String>[] ls; List[] la = new List[10]; ls = (List<String>[])la; // "Unchecked" warning ls[0] = new ArrayList<String>(); // Compile-time checking produces an error: //! ls[1] = new ArrayList<Integer>(); // The problem: List<String> is a subtype of Object Object[] objects = ls; // So assignment is OK // Compiles and runs without complaint: objects[1] = new ArrayList<Integer>(); // However, if your needs are straightforward it is // possible to create an array of generics, albeit // with an "unchecked" warning: List<BerylliumSphere>[] spheres = (List<BerylliumSphere>[])new List[10]; for(int i = 0; i < spheres.length; i++) spheres[i] = new ArrayList<BerylliumSphere>(); } }
Once you have a reference to a List[], you can see that you get some compile-time checking. The problem is that arrays are covariant, so a List[] is also an Object[], and you can use this to assign an ArrayList into your array, with no error at either compile time or run time.
If you know you're not going to upcast and your needs are relatively simple, however, it is possible to create an array of generics, which will provide basic compile-time type checking. However, a generic container will virtually always be a better choice than an array of generics.
说您不能创建泛型类型的数组并不完全正确。确实,编译器不会让您实例化泛型类型的数组。但是,它会让您创建对此类数组的引用。例如:
List<String>[] ls;
这毫无怨言地通过编译器。虽然您不能创建一个包含泛型的实际数组对象,但您可以创建一个非泛型类型的数组并对其进行转换:
//: arrays/ArrayOfGenerics.java // It is possible to create arrays of generics. import java.util.*; public class ArrayOfGenerics { @SuppressWarnings("unchecked") public static void main(String[] args) { List<String>[] ls; List[] la = new List[10]; ls = (List<String>[])la; // "Unchecked" warning ls[0] = new ArrayList<String>(); // Compile-time checking produces an error: //! ls[1] = new ArrayList<Integer>(); // The problem: List<String> is a subtype of Object Object[] objects = ls; // So assignment is OK // Compiles and runs without complaint: objects[1] = new ArrayList<Integer>(); // However, if your needs are straightforward it is // possible to create an array of generics, albeit // with an "unchecked" warning: List<BerylliumSphere>[] spheres = (List<BerylliumSphere>[])new List[10]; for(int i = 0; i < spheres.length; i++) spheres[i] = new ArrayList<BerylliumSphere>(); } }
一旦获得了对 List[] 的引用,您就可以看到进行了一些编译时检查。问题是数组是协变的,所以 List[] 也是一个 Object[],您可以使用它来将 ArrayList 分配到您的数组中,在编译时或运行时都不会出错。
但是,如果您知道自己不会向上转型并且您的需求相对简单,则可以创建一个泛型数组,这将提供基本的编译时类型检查。然而,泛型容器实际上总是比泛型数组更好的选择。
回答by Abimaran Kugathasan
Arrays are covariant. That means they retain the type of their elements at runtime. Java's generics are not. They use type erasure to basically mask the implicit casting that is going on. It's important to understand that.
数组是协变的。这意味着它们在运行时保留其元素的类型。Java 的泛型不是。他们使用类型擦除来基本上掩盖正在进行的隐式转换。理解这一点很重要。
You need to use Array.newInstance()
你需要使用 Array.newInstance()
In addition, arrays carry runtime type information about their component type, that is, about the type of the elements contained. The runtime type information regarding the component type is used when elements are stored in an array in order to ensure that no "alien" elements can be inserted.
此外,数组携带有关其组件类型的运行时类型信息,即有关所包含元素的类型。当元素存储在数组中时,将使用有关组件类型的运行时类型信息,以确保不能插入“外来”元素。
For more details look here
欲了解更多详情,请看这里
回答by alain.janinm
This does not work because generic classes does not belong to Reifiable Types.
这不起作用,因为泛型类不属于Reifiable Types。
The JLS about Array creation expressionstates :
It is a compile-time error ifthe [class type] does not denote a reifiable type(§4.7). Otherwise, the [class type] may name any named reference type, even an abstract class type (§8.1.1.1) or an interface type (§9).
The rules above imply that the element type in an array creation expression cannot be a parameterized type, other than an unbounded wildcard.
如果[class type] 不表示可具体化的类型(第 4.7 节),则会出现编译时错误。否则,[类类型] 可以命名任何命名的引用类型,甚至是抽象类类型(第 8.1.1.1 节)或接口类型(第 9 节)。
上述规则意味着数组创建表达式中的元素类型不能是参数化类型,除非是无界通配符。
The definition of Reifiable Typesis :
Reifiable 类型的定义是:
Because some type information is erased during compilation, not all types are available at run time. Types that are completely available at run time are known as reifiable types.
A type is reifiable if and only if one of the following holds:
由于在编译期间会擦除某些类型信息,因此在运行时并非所有类型都可用。在运行时完全可用的类型称为可具体化的类型。
当且仅当以下条件之一成立时,类型才是可具体化的:
It refers to a non-generic class or interface type declaration.
It is a parameterized type in which all type arguments are unbounded wildcards (§4.5.1).
It is a raw type (§4.8).
It is a primitive type (§4.2).
It is an array type (§10.1) whose element type is reifiable.
It is a nested type where, for each type T separated by a ".", T itself is reifiable.
For example, if a generic class X<T> has a generic member class Y<U>, then the type X<?>.Y<?> is reifiable because X<?> is reifiable and Y<?> is reifiable. The type X<?>.Y<Object> is not reifiable because Y<Object> is not reifiable.
回答by Rohit
Let's start with question 2 first and then get back to question 1:
让我们先从问题 2 开始,然后再回到问题 1:
Question 2:
问题2:
> ArrayList[] pl2 = new ArrayList[10]; ArrayList[] pl3 = new ArrayList[10];
> ArrayList[] pl2 = new ArrayList[10]; ArrayList[] pl3 = 新的 ArrayList[10];
What is the difference as far as the reference declaration of p12 and p13 is concerned?
就 p12 和 p13 的引用声明而言,有什么区别?
In pl2 ensures better type safety than p13.
在 pl2 中确保比 p13 更好的类型安全。
If I write for pl2:
如果我为 pl2 写作:
pl2[0]=new ArrayList<String>();
it will give me a compiler error stating "cannot convert from ArrayList<String>
to ArrayList<Integer>
"
它会给我一个编译器错误,指出“无法转换ArrayList<String>
为ArrayList<Integer>
”
Thus it ensures compile time safety.
因此它确保了编译时的安全性。
However if I write for p13
但是,如果我为 p13 写作
pl3[0]=new ArrayList<String>();
pl3[1]=new ArrayList<Integer>();
it will not throw any error and the onus will be on the developer to code and check properly while extracting data from p13, to avoid any unsafe type conversion during runtime.
它不会抛出任何错误,开发人员有责任在从 p13 提取数据时正确编码和检查,以避免在运行时发生任何不安全的类型转换。
Question 1:
问题 1:
That's just probably the way generics work. During the main array initialization, ArrayList<Integer>[] pl2 = new ArrayList[10]
, the left hand side, ArrayList<Integer>[] pl2
, will ensure type safety only when you initialize the ArrayList object in the index position:
这可能就是泛型的工作方式。在主数组初始化期间ArrayList<Integer>[] pl2 = new ArrayList[10]
,左手边的 ,ArrayList<Integer>[] pl2
只有在索引位置初始化 ArrayList 对象时才会确保类型安全:
pl2[0]=new ArrayList<Integer>();
The right hand side main array declaration = new ArrayList[10]
just ensures that the index position will hold ArrayList type items. Also have a look at type erasure concepts in Type Erasurefor more information.
右侧的主数组声明= new ArrayList[10]
只是确保索引位置将保存 ArrayList 类型的项目。另请查看类型擦除中的类型擦除概念以获取更多信息。
回答by pulasthi
Question 1.
问题 1。
Well, it's not the correct syntax. Hence that does not work.
好吧,这不是正确的语法。因此这是行不通的。
Question 2.
问题2。
ArrayList<Integer>[] pl2 = new ArrayList[10];
ArrayList[] pl3 = new ArrayList[10];
Since pl2 is defined with generic type <Integer> at compile time, the compiler will be know that pl2 is only allowed to have Integers and if you try to assign somthing other than Integers you will be alerted and compilation will fail.
由于 pl2 在编译时定义为泛型类型 <Integer>,编译器将知道 pl2 只允许具有整数,如果您尝试分配整数以外的内容,您将收到警报并且编译将失败。
In pl3 since there is no generic type you can assign any type of object to the list.
在 pl3 中,由于没有泛型类型,您可以将任何类型的对象分配给列表。
回答by M Sach
Question1
问题1
You cannot create arrays of parameterized types
您不能创建参数化类型的数组
Question 2
问题2
ArrayList<Integer>[] pl2 = new ArrayList[10];
It means you are telling to compiler that you are going to create array which will store arraylist of integers. Your arraylist will only contain Integer objects. That's where generics comes in. Generics make your code more safer and reliable. If you are sure your list should only contain integer objects, you should always go ahead with this.
这意味着您告诉编译器您将创建一个数组,该数组将存储整数数组列表。您的数组列表将仅包含 Integer 对象。这就是泛型的用武之地。泛型使您的代码更安全可靠。如果你确定你的列表应该只包含整数对象,你应该总是继续这样做。
But when you say
但是当你说
ArrayList[] pl3 = new ArrayList[10];
it means arraylist can store any object type like string, integer, custom objects, etc.
这意味着 arraylist 可以存储任何对象类型,如字符串、整数、自定义对象等。
回答by aymankoo
ArrayList<Integer>[] pl2 = new ArrayList<Integer>[10];
Means you don't need to do casting when you retrive data from the ArrayList example in normal case
意味着在正常情况下从 ArrayList 示例中检索数据时不需要进行转换
ArrayList[] pl2 = new ArrayList[10];
pl2.put(new Integer(10));
Integer i = p12.get(0); // this is wrong
Integer i = (Integer)p12.get(0); // this is true with casting
but
但
ArrayList<Integer>[] pl2 = new ArrayList<Integer>[10];
pl2.put(new Integer(10));
Integer i = p12.get(0); // this is true no need for casting
回答by Michal Borek
Problems with generics are by default issued as a warning by the compiler.
泛型问题默认由编译器作为警告发出。
After compilation, because of type erasure, they all become ArrayList[] pl2 = new ArrayList[10]
, but the compiler warns you that this is not good.
编译后,因为类型擦除,都变成了ArrayList[] pl2 = new ArrayList[10]
,但是编译器警告你这不好。
Generics have been added to Java, and to be backwards compatible you can use generic with non-generic interchangeably.
泛型已添加到 Java 中,为了向后兼容,您可以互换使用泛型和非泛型。
回答by Genjuro
It seems like you cannot create an array of arraylists with a generic type, according to an answer to Stack Overflow question Create an array of ArrayList elements.
根据Stack Overflow 问题Create an array of ArrayList elements的答案,您似乎无法创建具有泛型类型的数组列表。