【问题标题】:Java Generics Syntax for arrays数组的 Java 泛型语法
【发布时间】:2010-09-16 04:22:17
【问题描述】:

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

 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&lt;ArrayList&gt; 指定List 必须包含的内容,但List&lt;ArrayList&gt;[] 指定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();
  • 看起来所有泛型类型参数都已从您的代码示例中删除。之所以会发生这种情况,是因为您将它包含在 PRE 标记中,并且该站点将类型参数解释为格式错误或禁止的 HTML 标记(根据 Q31657)。您应该可以对其进行编辑。

标签: java generics syntax types


【解决方案1】:

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

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

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

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

这是编译器的输出:

javac Generics2.java -Xlint:unchecked

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

这是我的测试。

导入 java.util.ArrayList; 导入 java.util.List; 导入 java.util.LinkedList; 公共类泛型2 { 公共静态无效主要(字符串[]参数){ List[] 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)); 返回整数列表; } }

【讨论】:

  • 您应该能够编辑您的原始帖子以包含上述代码,这比将其作为答案发布更好
【解决方案2】:

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

所以这个:

List<ArrayList>[] myArray

真正的意思是:

List[] myArray

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

Naftalin 和 Wadler 所著的《Java Generics and Collections》一书是一本很好的参考书,可以帮助您解答有关泛型的问题。或者,当然,Generics FAQ 是您的规范在线参考。

【讨论】:

    【解决方案3】:

    你说得对:

    经过一些测试,我确定声明是指一个数组,其中每个元素都是一个 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>();
    

    【讨论】:

      【解决方案4】:

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

      所以,你说的是(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);
                      }
                  }
              }
          }
      }
      

      【讨论】:

        【解决方案5】:
        List<ArrayList>[] someListArray;
        

        给你一个:

        array of ( List of ArrayList )
        

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

        array of List
        

        然后投射它:

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

        【讨论】:

          【解决方案6】:

          乔什·布洛赫先生说:

          "首选列表而不是数组,因为数组 是协变的,泛型是 不变'

          你也许可以这样做:

          List<List<ArrayList>> someListArray;
          

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

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

          【讨论】:

          • 我“不需要”这个。我在代码维护期间遇到了声明,并试图理解声明的含义。
          猜你喜欢
          • 2012-08-29
          • 1970-01-01
          • 2015-08-11
          • 1970-01-01
          • 2015-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多