数组的Java泛型语法



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

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

答案是数组只能容纳具体化的类型。一般化的类并没有具体化。也就是说,List<数组列表>只是列表。泛型在运行时被擦除(谷歌"擦除墙"了解更多信息)。

所以这个:

List<ArrayList>[] myArray

真正的意思是:

List[] myArray

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

Naftalin和Wadler的《Java泛型和集合》一书是您可能会遇到的关于泛型的问题的绝佳参考。或者,当然,Generics FAQ是您的规范在线参考。

Josh Bloch先生说:

"因为数组,所以更喜欢列表是协变的,泛型是不变量

你也许可以这样做:

List<List<ArrayList>> someListArray;

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

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

List<ArrayList>[] someListArray;

给你一个:

array of ( List of ArrayList )

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

array of List

并铸造:

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

List是一个能够容纳ArrayList对象的ListList[]是这样的Lists 的数组

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

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

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

你说得对:

在运行了一些测试之后,我确定声明意味着一个数组,其中每个元素都是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>();

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

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

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

从编译器的角度来看,返回List[]的方法可能是返回List<数组列表>(满足声明),否则可能不会。类似地,返回List的方法可能返回也可能不返回ArrayList。

以下是编译器输出:

javacGenerics2.java-Xlint:未检查

Generics2.java:12:警告:未检查的转换已找到: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{public static void main(String[]args){列表<数组列表>[]someListArray;someListArray=getArrayWhereEachElementIsALinkedListObject();//为什么这符合声明?//someListArray[0]=>包含字符串的LinkedList对象someListArray=getArrayWhereEachElementIsAListOfLinkedListObjects();//someListArray[0]=>包含LinkedList对象的LinkedList}public static List[]getArrayWhereEachElementIsALinkedListObject(){List[]arrayOfLists=新的LinkedList[2];arrayOfLists[0]=getStringLinkedListAsList();arrayOfLists[1]=getIntegerLinkedListAsList();return arrayOfLists;}public static List[]getArrayWhereEachElementIsAListOfLinkedListObjects(){List list1=新的LinkedList();list1.add(new LinkedList());List list2=新的LinkedList();list2.add(new LinkedList());List[]arrayOfListsOfLinkedLists=新的LinkedList[2];arrayOfListsOfLinkedLists[0]=列表1;arrayOfListsOfLinkedLists[1]=列表2;return arrayOfListsOfLinkedLists;}公共静态列表getStringLinkedListAsList(){List字符串List=新的LinkedList();stringList.add("一");stringList.add("两个");return字符串列表;}公共静态列表getIntegerLinkedListAsList(){List intList=新的LinkedList();intList.add(new Integer(1));intList.add(new Integer(2));return intList;}}

最新更新