Java Generics Syntax for arrays

前端 未结 6 1620
梦谈多话
梦谈多话 2020-12-10 12:17

What data structure does the following declaration specify?

 List[] myArray;

I think it should declare an array where each

相关标签:
6条回答
  • 2020-12-10 12:51

    Mr Josh Bloch says:

    "Prefer lists to array because arrays are covariant and generics are invariant'

    You could perhaps do:

    List<List<ArrayList>> someListArray;
    

    This may give some performance hit (not even noticable i bet) but you will get better type safety at compile time.

    but I think the question should be more around "why" you need this?

    0 讨论(0)
  • 2020-12-10 13:00

    List is a List capable of holding ArrayList objects List [] is an array of such Lists

    So, what you said is that An Array of (List of ArrayList object) is CORRECT.

    Can you share what your tests were. My own tests are different

    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);
                    }
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-10 13:03

    After running some additional tests, I think I have my answer.

    List<ArrayList>[] does indeed specify an array where each element is a List of ArrayList objects.

    Compiling the code as shown below revealed why my first test allowed me to use an array where each element is a List of anything. Using return types of List[] and List in the methods that populate the arrays did not provide the compiler enough information to prohibit the assignments. But the compiler did issue warnings about the ambiguity.

    From the compiler's point of view, a method returning a List[] might be returning a List<ArrayList> (which satisfies the declaration) or it might not. Similarly, a method returning a List might or might not return an ArrayList.

    Here was the compiler output:

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

    Here are my tests.

    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();
            // Why does this satisfy the declaration?
            //someListArray[0] => LinkedList object holding Strings
    
            someListArray= getArrayWhereEachElementIsAListOfLinkedListObjects();
            //someListArray[0] => LinkedList object holding LinkedList objects
    
        }
    
        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;
        }
    
    }
    
    0 讨论(0)
  • 2020-12-10 13:04

    You are correct in saying:

    After running some tests, I determined the declaration means an array where each element is an ArrayList object.

    Executing this code

    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;
    

    Produces this result:

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

    It seems to me there is no reason not to do this instead:

    List<ArrayList> myArray  = new ArrayList<ArrayList>();
    
    0 讨论(0)
  • 2020-12-10 13:05
    List<ArrayList>[] someListArray;
    

    gives you an:

    array of ( List of ArrayList )
    

    But due to limitations in Java generics (bug 6229728) you can only actually create:

    array of List
    

    and cast it:

    List<ArrayList>[] someListArray = (List<ArrayList>[]) new List[5];
    
    0 讨论(0)
  • 2020-12-10 13:09

    The answer is that arrays can only hold reified types. And generified classes are not reified. That is, the runtime "type" of the List<ArrayList> is just List. Generics are erased at runtime (google "wall of erasure" for more).

    So this:

    List<ArrayList>[] myArray
    

    really means:

    List[] myArray
    

    There is no type-safe way to declare what you're trying to declare. Generally, I'd recommend you use a List instead of an array in this case. Some people have gone so far as to suggest that arrays should be treated as deprecated types now that we have generics. I can't say I'm willing to go that far but you should consider whether a collection is a better alternative whenever you're drawn to an array.

    The book Java Generics and Collections by Naftalin and Wadler is an excellent reference for questions you might have about generics. Or, of course, the Generics FAQ is your canonical online reference.

    0 讨论(0)
提交回复
热议问题