developer747
developer747

Reputation: 15928

Java initializing a generic array

  T[] genericArray= (T[])(new Object[2]);

T has a constraint that it implements Comparable. The line above fails with an exception

" java.lang.ClassCastException: [Ljava.lang.Object; 
cannot be cast to [Ljava.lang.Comparable;

How do I initialize a generic array where the T has constraints?

Upvotes: 0

Views: 6094

Answers (2)

Hoopje
Hoopje

Reputation: 12932

You get this error because Object does not implement Comparable and thus Object[] is not a sub-type of Comparable[] (which, because of type erasure, is the runtime type of your genericArray).

The underlying problem is that you want to create a generic array. This is not possible in Java. The reason is, that unlike generics, the type of the elements of an array is known at runtime. If you write new T[], it is not known which type of array must be created.

You try to circumvent this by creating an array of some supertype. But this is also not correct (and you should get a warning if you do it). If you create a an array with new Comparable[size], you create a an array of Comparables, not an array of some subtype of Comparable. A T[] might be a String[] or a Long[], and String[] and Long[] are different types than Comparable[] (also at runtime).

To demonstrate the problem, consider the following program:

public class Foo<T extends Comparable> {    
    T[] createArray() {
        return (T[])new Comparable[1];
    }

    public static void main(String... args) {
        Foo<String> foo = new Foo<>();
        String[] ss = foo.createArray(); // here
    }
}

It might look perfectly okay at first sight, but when your run it, you get a ClassCastException, because in the marked line a Object[] is cast to a String[].

The solution is to use Class<T> objects as so-called type tokens. These let you store the type so that you can access it at run-time. Now you can create an array with the correct type by using Array.newInstance(Class<T>, int...). For example:

public class Foo<T extends Comparable> {
    private Class<T> type;

    public Foo(Class<T> type) {
        this.type = type;
    }

    T[] createArray() {
        return (T[])Array.newInstance(type, 1);
    }

    public static void main(String... args) {
        Foo<String> foo = new Foo<>(String.class);
        String[] ss = foo.createArray();
    }
}

(You may still get a warning from the compiler, because newInstance's return type is Object. You can ignore it because the object it returns is an array of the correct type.)

Upvotes: 1

Davide Lorenzo MARINO
Davide Lorenzo MARINO

Reputation: 26926

Object doesn't implements Comparable.

Instead of creating it as Object[] create it as Comparable[].

Related to your comment:

A variable can be declared of any type. When you create an array you are not creating objects inside the array, but you are only allocating the memory to store the references to the objects.

So as you can write:

Comparable x = "Pippo"; // Because String is Comparable

you can also write

Comparable[] x = new Comparable[1];
x[0] = "Pippo";    // Here you add a concrete String that is a
                   // Comparable type on the first position

Upvotes: 3

Related Questions