16

以下声明指定了什么数据结构?

 List<ArrayList>[] myArray;

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

我的推理:

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

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

所以List<ArrayList>指定了List必须包含的内容,但List<ArrayList>[]指定了List必须如何实现。

我错过了什么吗?

这是我的测试。

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


public class Generics1 {

    public static void main(String[] args) {

        List<ArrayList>[] 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;
    }
}
4

6 回答 6

17

答案是数组只能保存具体类型。并且泛型类没有具体化。也就是说,List<ArrayList> 的运行时“类型”只是 List。泛型在运行时被擦除(谷歌“擦除墙”更多)。

所以这:

List<ArrayList>[] myArray

真正意思:

List[] myArray

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

Naftalin 和 Wadler所著的Java Generics and Collections一书对于您可能遇到的有关泛型的问题是一本极好的参考书。或者,当然,泛型常见问题解答是您的规范在线参考。

于 2008-10-09T13:37:26.317 回答
8

乔什·布洛赫先生说:

“更喜欢列表而不是数组,因为数组是协变的,而泛型是不变的”

你也许可以这样做:

List<List<ArrayList>> someListArray;

这可能会给性能带来一些影响(我敢打赌甚至不会引起注意),但您会在编译时获得更好的类型安全性。

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

于 2008-10-09T01:40:58.793 回答
5
List<ArrayList>[] someListArray;

给你一个:

array of ( List of ArrayList )

但是由于 Java 泛型的限制(错误6229728),您只能实际创建:

array of List

并投射它:

List<ArrayList>[] someListArray = (List<ArrayList>[]) new List[5];
于 2008-10-09T01:44:42.013 回答
0

你说得对:

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

执行此代码

List<ArrayList>[] myArray  = new ArrayList[2];

myArray[0] = new ArrayList<String>();
myArray[0].add("test 1");

myArray[1] = new ArrayList<String>();
myArray[1].add("test 2");

print myArray;

产生这个结果:

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

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

List<ArrayList> myArray  = new ArrayList<ArrayList>();
于 2008-10-09T01:49:29.600 回答
0

List 是一个能够保存 ArrayList 对象的 List List [] 是一个此类 List 的数组

因此,您所说的是(ArrayList 对象的列表)的数组是正确的。

你能分享你的测试是什么。我自己的测试不一样

import java.util.*;

public class TestList {
    public static void main(String ... args) {
        class MySpecialLinkedList extends LinkedList<ArrayList<Integer>> {
            MySpecialLinkedList() {

            }

            public void foo() {

            }


            public Object clone()
            {
                return super.clone();
            }
        }

        List<ArrayList<Integer>> [] someListArray = new MySpecialLinkedList[10];
        for (int i = 0; i < 10; ++i) {
            someListArray[i] = new LinkedList<ArrayList<Integer>>();
            for (int j = 0; j < 20; ++j) {
                someListArray[i].add(new ArrayList<Integer>());
                for (int k = 0; k < 30; ++k) {
                    someListArray[i].get(j).add(j);
                }
            }
        }
    }
}
于 2008-10-09T02:47:19.407 回答
0

在运行了一些额外的测试之后,我想我有了答案。

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

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

从编译器的角度来看,返回 List[] 的方法可能返回 List<ArrayList> (满足声明),也可能不返回。同样,返回 List 的方法可能会也可能不会返回 ArrayList。

这是编译器输出:

javac Generics2.java -Xlint:未选中

Generics2.java:12:警告:[unchecked] 未经检查的转换
找到:java.util.List[]
必需:java.util.List<java.util.ArrayList>[]
        someListArray = getArrayWhereEachElementIsALinkedListObject();
                                                                   ^
Generics2.java:16:警告:[未选中] 未选中的转换
找到:java.util.List[]
必需:java.util.List<java.util.ArrayList>[]
        someListArray= getArrayWhereEachElementIsAListOfLinkedListObjects();

这是我的测试。

导入 java.util.ArrayList;
导入 java.util.List;
导入 java.util.LinkedList;


公共类泛型2 {

    公共静态无效主要(字符串[]参数){

        List<ArrayList>[] someListArray;

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

        someListArray= getArrayWhereEachElementIsAListOfLinkedListObjects();
        //someListArray[0] => LinkedList 对象持有 LinkedList 对象

    }

    公共静态列表 [] getArrayWhereEachElementIsALinkedListObject() {
        List[] arrayOfLists = new LinkedList[2];
        arrayOfLists[0] = getStringLinkedListAsList();
        arrayOfLists[1] = getIntegerLinkedListAsList();
        返回数组列表;
    }

  公共静态列表 [] getArrayWhereEachElementIsAListOfLinkedListObjects() {

        列表 list1 = new LinkedList();
        list1.add(new LinkedList());

        列表 list2 = new LinkedList();
        list2.add(new LinkedList());

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

    公共静态列表 getStringLinkedListAsList() {
        列表 stringList= new LinkedList();
        stringList.add("one");
        stringList.add("两个");
        返回字符串列表;
    }


    公共静态列表 getIntegerLinkedListAsList() {
        列表 intList=new LinkedList();
        intList.add(新整数(1));
        intList.add(新整数(2));
        返回整数列表;
    }

}
于 2008-10-09T03:16:23.297 回答