1

I am a bit puzzled: I want an array of ArrayList-s but I see no way to specify the ArrayList item type:

class Test<V> {
    final static int N = 512;
    ArrayList<V> list1 = new ArrayList<>(); // ok
    ArrayList<V> list2 = new ArrayList<V>(); // ok

    ArrayList<V>[] lists1 = new ArrayList[N]; // <== warning:
    // Type safety: The expression of type ArrayList[] needs
    // unchecked conversion to conform to ArrayList<V>[]
    // Note that this line works because it's only a warning.

    ArrayList<V>[] lists2 = new ArrayList<V>[N]; // <== error:
    // Cannot create a generic array of ArrayList<V>

    ArrayList<V>[] lists3 = new ArrayList<>[N]; // <== error:
    // Incorrect number of arguments for type ArrayList<E>;
    // it cannot be parameterized with arguments <>

    ArrayList<V>[] lists4 = (ArrayList<V>[])new ArrayList[N]; // <== warning:
    //Type safety: Unchecked cast from ArrayList[] to ArrayList<V>[]

}

I see that the problem with

    ArrayList<V>[] lists1 = new ArrayList[N];

is that the type of items is not specified, but how do I specify it?

EDIT: the answer is that they disallowed raw arrays of parameterized types. They probably wanted the programmer to explicitly take responsibility for type safety. Or maybe they felt uneasy because Test.f() compiles without any warnings:

    void f() {
        lists1[0] = new ArrayList<V>(); // ok

        //lists1[1] = new ArrayList<String>(); // <== error:
        // Type mismatch: cannot convert from ArrayList<String> to ArrayList<V>

        Object[] x = lists1;
        x[0] = new ArrayList<Integer>(); // ok
    }

They probably decided that a warning in some barely relevant place is better than no warning at all.

18446744073709551615
  • 14,600
  • 3
  • 82
  • 116

5 Answers5

0

The only way to do this without warnings is simply an ArrayList of ArrayLists:

ArrayList<ArrayList<V>> list_of_lists = new ArrayList<>();
ArrayList<V> list = new ArrayList<>();
list_of_lists.add(list);
Michael
  • 34,340
  • 9
  • 58
  • 100
  • Please explain your downvotes... – Michael Dec 09 '16 at 10:08
  • The downvote wasn't mine (I'm too mean to spend my score on downvotes;), but I can explain: in my code the list-of-lists is within the loop that is most critical from the performance viewpoint. The array cannot grow, but it is faster, and BTW null pointers are faster than empty ArrayLists. – 18446744073709551615 Dec 09 '16 at 12:09
  • In that case, if you are sure an `ArrayList` of `ArrayList`s would have a critical performance impact (I'm dubious but I'm open to the possibility), I would use your `lists1` version but suppress the warning. By 'sure' I mean empirical evidence gained via profiling. – Michael Dec 09 '16 at 13:55
  • I use the `lists1` style and just ignore the warning. But I am really surprised to find out that there is _no way_ to eliminate it. – 18446744073709551615 Dec 09 '16 at 14:26
  • If it's a warning you know about and don't care about, it is best to suppress it. That way you tell the compiler and everyone looking at your code that its not something which will cause an issue. If you have a lot of warnings already, it can be difficult to see additional ones you introduce to the code which *may* have unwanted consequences. – Michael Dec 09 '16 at 14:50
0

There are some fundamental difference between arrays and generics. They don't mix well.

Arrays are reified, meaning that they enforce it's constraints at run time. On the other hand, generics enforce their constraint only at the compile time. And they erase the type information at run time.

Because of these difference they don't generally mix well. For example, following expressions are not valid:

ArrayList<V>[] lists2 = new ArrayList<V>[N];

ArrayList<V>[] lists3 = new ArrayList<>[N];

ArrayList<V>[] lists3 = new ArrayList<String>[N];

While this:

ArrayList<V>[] lists1 = new ArrayList[N];

is legal but not type safe. Meaning that at run time, it could very well fail with ClassCastException.

mohit
  • 4,428
  • 3
  • 19
  • 36
0

As per the Oracle documentation:

"You cannot create arrays of parameterized types"

Instead you can do something like:

List<List<ItemType>> var = new ArrayList<List<ItemType>>(size);
AlphaQ
  • 646
  • 8
  • 18
0

Simply you can not do it. You can create a list of lists or a set of lists but not an array of lists.

wertigom
  • 263
  • 2
  • 11
-1

You will specify it when you will instanciate your Test class. Though, such kind of structure should be put in a specific class so your generic parameter would be handled by that new class, and you wouldn't have any trouble when using it in your tests

Edit: That's why what I had in mind was something like

public class ArrayOfList<T> {

    private ArrayList<T>[] arrayLists;

    public ArrayList<T>[] getArrayLists() {
        return arrayLists;
    }


    public void setArrayLists(ArrayList<T>[] arrayLists) {
        this.arrayLists = arrayLists;
    }

}

public class Test {

    public void testArrayLists(){
        ArrayOfList<String> lists = new ArrayOfList<>();
        // lists contains a usable ArrayList<String>[]
    }
}
DamCx
  • 1,030
  • 1
  • 12
  • 22