33

Why can't I create an array of List ?

List<String>[] nav = new List<String>[] { new ArrayList<String>() };

Eclipse says "Cannot create a generic array of List"

or

ArrayList<String>[] nav = new ArrayList<String>[] { new ArrayList<String>() };

Eclipse says "Cannot create a generic array of ArrayList"

or

List<String>[] getListsOfStrings() {
    List<String> groupA = new ArrayList<String>();
    List<String> groupB = new ArrayList<String>();
    return new List<String>[] { groupA, groupB };
}

But I can do this:

List[] getLists() {
    return new List[] { new ArrayList(), new ArrayList() };
}

Eclipse says that List and ArrayList are raw types but it compiles...

Seems pretty simple, why won't it work?

skaffman
  • 398,947
  • 96
  • 818
  • 769
Mike
  • 1,390
  • 1
  • 12
  • 17
  • 2
    possible duplicate of [Java Generics Syntax for arrays](http://stackoverflow.com/questions/185594/java-generics-syntax-for-arrays) – Joachim Sauer Apr 14 '11 at 11:29

4 Answers4

29

Well, generics tutorial give the answer to your question.

The component type of an array object may not be a type variable or a parameterized type, unless it is an (unbounded) wildcard type.You can declare array types whose element type is a type variable or a parameterized type, but not array objects.

This is annoying, to be sure. This restriction is necessary to avoid situations like:

// Not really allowed.
List<String>[] lsa = new List<String>[10];
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
// Unsound, but passes run time store check
oa[1] = li;

// Run-time error: ClassCastException.
String s = lsa[1].get(0);

If arrays of parameterized type were allowed, the previous example would compile without any unchecked warnings, and yet fail at run-time. We've had type-safety as a primary design goal of generics.

Czechnology
  • 14,832
  • 10
  • 62
  • 88
Gursel Koca
  • 20,940
  • 2
  • 24
  • 34
  • 9
    "If arrays of parameterized type were allowed, the example above would compile without any unchecked warnings, and yet fail at run-time." This is not the reason. `Object[] sa = new String[10]; oa[1] = new Integer(3);` would also "compile without any unchecked warnings, and yet fail at run-time". The more important point is that it should fail at the point of storing, with an ArrayStoreException (thus arrays are runtime-checked). But the runtime check cannot check generics, that's why creating arrays of parameterized types is disallowed. – newacct Dec 17 '12 at 21:26
14

You can't create arrays of generic types, generally.

The reason is that the JVM has no way to check that only the right objects are put into it (with ArrayStoreExceptions), since the difference between List<String> and List<Integer> are nonexistent at runtime.

Of course, you can trick the compiler by using the raw type List or the unbound wildcard type List<?>, and then cast it (with a unchecked cast) to List<String>. But then it is your responsibility to put only List<String> in it and no other lists.

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
1

No exact answer, but a tip:

Last example has a raw type warning because you omitted the typization of the list; it is generally a better (type safe) approach to specify which object types are contained in the list, which you already did in the previous examples (List<String> instead of List).

Using arrays is not best practice, since their use contains errors most times; Using Collection classes (List, Set, Map,...) enables use of typization and of convenient methods for handling their content; just take a look at the static methods of the Collections class.

Thus, just use the example of the previous answer.

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
Andreas
  • 2,211
  • 1
  • 18
  • 36
  • But you can't create an array of `List` – that is the point of the question (and the reason the last example was used at all). – Paŭlo Ebermann Mar 17 '15 at 09:16
0

Another solution is to extend LinkedList<String> (or ArrayList<String>, etc.), then create an array of the subclass.

private static class StringList extends LinkedList<String> {}

public static void main(String[] args)
{
    StringList[] strings = new StringList[2];
    strings[0] = new StringList();
    strings[1] = new StringList();
    strings[0].add("Test 1");
    strings[0].add("Test 2");
    strings[1].add("Test 3");
    strings[1].add("Test 4");
    System.out.println(strings[0]);
    System.out.println(strings[1]);
}
Chris
  • 21