Java泛型数组的语法

16

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

 List<ArrayList>[] myArray;

我认为它应该声明一个数组,其中每个元素都是一个List(例如一个LinkedListArrayList),并要求每个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;
    }
}

每个元素很可能被分配为myArray[0] = new ArrayList<ArrayList>();。 - James Schek
看起来你的代码示例中所有的通用类型参数都被剥离了。这可能是因为你将其包含在PRE标签中,网站将类型参数解释为格式不正确或禁止使用的HTML标签(参见Q31657)。你应该可以编辑它。 - Alan Moore
6个回答

17
答案:数组只能保存具体化(reified)的类型,而泛型类不具体化。也就是说,List<ArrayList> 这个运行时“类型”只是 List。泛型在运行时会被擦除(可以搜索“擦除墙”了解更多信息)。

因此,以下代码:

List<ArrayList>[] myArray

真正的意思是:

List[] myArray

声明你尝试声明的内容没有类型安全的方式。通常情况下,我会建议你在这种情况下使用List而不是数组。有些人甚至建议现在我们有了泛型后,应该将数组视为已弃用的类型。我不能说我愿意走得那么远,但是每当你想要使用数组时,你应该考虑集合是否是更好的选择。

书籍《Java Generics and Collections》由Naftalin和Wadler编写,是关于泛型问题的优秀参考书。当然,Generics FAQ也是你的在线参考书。


8

Josh Bloch先生说:

"使用列表而不是数组,因为数组是协变的,而泛型是不变的"

你可以这样做:

List<List<ArrayList>> someListArray;

这可能会稍微影响一些性能(我敢打赌你甚至都不会注意到),但是你在编译时将获得更好的类型安全。

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


我不是“需要”这个。在代码维护过程中,我偶然遇到了这个声明,并试图理解它的含义。 - user19685

5
List<ArrayList>[] someListArray;

为您提供:

array of ( List of ArrayList )

但是由于Java泛型的限制(错误6229728),您只能创建以下内容:

array of List

并将其转换:

List<ArrayList>[] someListArray = (List<ArrayList>[]) new List[5];

0

经过运行一些额外的测试,我认为我有了答案。

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

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

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

以下是编译器输出:

javac Generics2.java -Xlint:unchecked

Generics2.java:12: warning: [unchecked] unchecked conversion
found   : java.util.List[]
required: java.util.List<java.util.ArrayList>[]
        someListArray = getArrayWhereEachElementIsALinkedListObject();
                                                                   ^
Generics2.java:16: warning: [unchecked] unchecked conversion
found   : java.util.List[]
required: java.util.List<java.util.ArrayList>[]
        someListArray= getArrayWhereEachElementIsAListOfLinkedListObjects();

这是我的测试。

import java.util.ArrayList;
import java.util.List;
import java.util.LinkedList;
public class Generics2 {
public static void main(String[] args) {
List<ArrayList>[] 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("one"); stringList.add("two"); return stringList; }
public static List getIntegerLinkedListAsList() { List intList= new LinkedList(); intList.add(new Integer(1)); intList.add(new Integer(2)); return intList; }
}

你应该能够编辑你的原始帖子,包括上述代码,这比将其作为答案发布要好。 - Jean

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>();

0

List是一个能够容纳ArrayList对象的列表

List []是这些列表的数组

所以,你说的是“(List of ArrayList object)的数组”是正确的。

你能分享一下你的测试结果吗?我的测试结果不同。

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);
                }
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接