Java Generics数组语法

以下声明指定了哪种数据结构?

List[] myArray; 

我认为它应该声明一个数组,其中每个元素是一个List (例如, LinkedListArrayList ),并要求每个List包含ArrayList对象。

我的推理:

  List someList; // A List of String objects List someList; // A List of ArrayList objects List[] someListArray; // An array of List of ArrayList objects 

在运行一些测试之后,我确定它接受一个数组,其中每个元素都是LinkedList对象,并且没有指定LinkedList对象包含的内容。

因此List指定List必须包含的内容,但List[]指定List必须如何实现。

我错过了什么吗?

这是我的测试。

 import java.util.ArrayList; import java.util.List; import java.util.LinkedList; public class Generics1 { public static void main(String[] args) { List[] someListArray; someListArray = getArrayWhereEachElementIsAnArrayListObject(); // Why does this satisfy the declaration? //someListArray[0] => ArrayList object holding Strings someListArray= getArrayWhereEachElementIsAListOfArrayListObjects(); //someListArray[0] => ArrayList object holding ArrayList objects } public static List[] getArrayWhereEachElementIsAnArrayListObject() { List[] arrayOfLists = new ArrayList[2]; arrayOfLists[0] = getStringList(); arrayOfLists[1] = getIntegerList(); return arrayOfLists; } public static List[] getArrayWhereEachElementIsAListOfArrayListObjects() { List list1 = new ArrayList(); list1.add(getArrayList()); List list2 = new ArrayList(); list2.add(getArrayList()); List[] arrayOfListsOfArrayLists = new ArrayList[2]; arrayOfListsOfArrayLists[0] = list1; arrayOfListsOfArrayLists[1] = list2; return arrayOfListsOfArrayLists; } public static List getStringList() { List stringList= new ArrayList(); stringList.add("one"); stringList.add("two"); return stringList; } public static List getIntegerList() { List intList= new ArrayList(); intList.add(new Integer(1)); intList.add(new Integer(2)); return intList; } public static ArrayList getArrayList() { ArrayList arrayList = new ArrayList() ; return arrayList; } } 

答案是数组只能保存有效类型。 并且一般化的课程没有具体化。 也就是说,List 的运行时“类型”只是List。 generics在运行时被删除(谷歌“擦除墙”更多)。

所以这:

 List[] myArray 

真正意思:

 List[] myArray 

没有类型安全的方法来声明您要声明的内容。 通常,在这种情况下,我建议您使用List而不是数组。 有些人甚至建议在我们有generics的情况下将数组视为已弃用的类型。 我不能说我愿意走那么远但是你应该考虑一下,当你被一个arrays吸引时,一个集合是否是一个更好的选择。

Naftalin和Wadler的Java Generics and Collections一书是您对generics问题的极好参考。 或者,当然, generics常见问题解答是您的规范在线参考。

Josh Bloch先生说:

“首选列表到数组,因为数组是协变的,而generics是不变的’

你也许可以这样做:

 List> someListArray; 

这可能会给性能带来一些打击(甚至不值得我注意),但是在编译时你会获得更好的类型安全性。

但我认为问题应该更多地围绕“为什么”你需要这个?

 List[] someListArray; 

给你一个:

 array of ( List of ArrayList ) 

但是由于Javagenerics的限制(bug 6229728 ),你只能实际创建:

 array of List 

投下它:

 List[] someListArray = (List[]) new List[5]; 

List是一个能够保存ArrayList对象的List List []是这样一个列表的数组

所以,你所说的是一个(ArrayList对象列表)的数组是正确的。

你能分享你的测试吗? 我自己的测试是不同的

 import java.util.*; public class TestList { public static void main(String ... args) { class MySpecialLinkedList extends LinkedList> { MySpecialLinkedList() { } public void foo() { } public Object clone() { return super.clone(); } } List> [] someListArray = new MySpecialLinkedList[10]; for (int i = 0; i < 10; ++i) { someListArray[i] = new LinkedList>(); for (int j = 0; j < 20; ++j) { someListArray[i].add(new ArrayList()); for (int k = 0; k < 30; ++k) { someListArray[i].get(j).add(j); } } } } } 

你说的是对的:

在运行一些测试之后,我确定声明意味着一个数组,其中每个元素都是一个ArrayList对象。

执行此代码

 List[] myArray = new ArrayList[2]; myArray[0] = new ArrayList(); myArray[0].add("test 1"); myArray[1] = new ArrayList(); myArray[1].add("test 2"); print myArray; 

产生这个结果:

 {["test 1"], ["test 2"]} 

在我看来,没有理由不这样做:

 List myArray = new ArrayList(); 

经过一些额外的测试,我想我有答案。

List []确实指定了一个数组,其中每个元素都是ArrayList对象的List。

编译如下所示的代码揭示了为什么我的第一个测试允许我使用一个数组,其中每个元素都是List的任何东西。 在填充数组的方法中使用List []和List的返回类型不会为编译器提供足够的信息来禁止分配。 但是编译器确实发出了关于模糊性的警告。

从编译器的角度来看,返回List []的方法可能会返回List (它满足声明),也可能不会。 类似地,返回List的方法可能会也可能不会返回ArrayList。

这是编译器输出:

javac Generics2.java -Xlint:未选中

 Generics2.java:12:警告:[未选中]未经检查的转换
发现:java.util.List []
必需:java.util.List  []
         someListArray = getArrayWhereEachElementIsALinkedListObject();
                                                                    ^
 Generics2.java:16:警告:[未选中]未经检查的转换
发现:java.util.List []
必需:java.util.List  []
         someListArray = getArrayWhereEachElementIsAListOfLinkedListObjects();

这是我的测试。

 import java.util.ArrayList;
 import java.util.List;
 import java.util.LinkedList;


公共类Generics2 {

     public static void main(String [] args){

         List  [] someListArray;

         someListArray = getArrayWhereEachElementIsALinkedListObject();
         //为什么这满足声明?
         // someListArray [0] =>持有字符串的LinkedList对象

         someListArray = getArrayWhereEachElementIsAListOfLinkedListObjects();
         // someListArray [0] =>包含LinkedList对象的LinkedList对象

     }

     public static List [] getArrayWhereEachElementIsALinkedListObject(){
         List [] arrayOfLists = new LinkedList [2];
         arrayOfLists [0] = getStringLinkedListAsList();
         arrayOfLists [1] = getIntegerLinkedListAsList();
         return arrayOfLists;
     }

   public static List [] getArrayWhereEachElementIsAListOfLinkedListObjects(){

         List list1 = new LinkedList();
         list1.add(new LinkedList());

         List list2 = new LinkedList();
         list2.add(new LinkedList());

         List [] arrayOfListsOfLinkedLists = new LinkedList [2];
         arrayOfListsOfLinkedLists [0] = list1;
         arrayOfListsOfLinkedLists [1] = list2;
         return arrayOfListsOfLinkedLists;
     }

     public static List getStringLinkedListAsList(){
         List stringList = new LinkedList();
         stringList.add( “1”);
         stringList.add( “二”);
         return stringList;
     }


     public static List getIntegerLinkedListAsList(){
         List intList = new LinkedList();
         intList.add(new Integer(1));
         intList.add(new Integer(2));
         return intList;
     }

 }