6

Possible Duplicate:
Java how to: Generic Array creation
Error: Generic Array Creation

I am getting this error:

Cannot create a generic array of T

This is my code (error on line 6):

1    public class HashTable<T> {
2    
3        private T[] array;
4    
5        HashTable(int initSize) {
6            this.array = new T[initSize];
7        }
8    }

I am wondering why this error is appearing and the best solution to fix it. Thanks.

UPDATE:

I adjusted my code so that the array is taking in linked lists instead, but I am getting a new error.

Here is my error:

Cannot create a generic array of LinkedList<T>

Here is my code (error on line six):

1    public class HashTable<T> {
2    
3        private LinkedList<T>[] array;
4    
5        HashTable(int initSize) {
6            this.array = new LinkedList<T>[initSize];
7        }
8    }

Is this error for the exact same reason? I was just assuming I could create generic linked lists and just store them in the array.

Community
  • 1
  • 1
Pat Murray
  • 3,545
  • 6
  • 23
  • 32
  • 1
    It might not be possible: http://stackoverflow.com/a/217110 (thought that's not quite the same thing) – Rup May 01 '12 at 13:38
  • 3
    http://stackoverflow.com/questions/529085/java-how-to-generic-array-creation – Luca May 01 '12 at 13:41
  • It's because of type erasure, see: http://docs.oracle.com/javase/tutorial/java/generics/erasure.html – CodeClown42 May 01 '12 at 13:42
  • You don't want an Array of linked lists - you just want a single linked list (or ArrayList) and treat that as an array! i.e. exactly as AlexR's answer. An ArrayList is a simple Collection wrapper around an array. – Rup May 01 '12 at 16:16
  • I am actually implementing a hash table (for a certain implementation) requires the array to be holding array lists. I've found that the simple casting method works best for my scenario. (LinkedList[])(new LinkedList[initSize]) – Pat Murray May 01 '12 at 16:22

3 Answers3

8

Yes, generic arrays cannot be created. The best workaround I know is to use collections instead:

private List<T> list;

.......

list = new ArrayList<T>();
AlexR
  • 109,181
  • 14
  • 116
  • 194
3

Generic arrays can be created via reflection (although an unsafe cast is required), you just need to pass the class as a parameter (assuming that the following method is inside a class that defines a <T> type parameter):

@SuppressWarnings("unchecked")
public T[] createArray(Class<T> klass, int size) {
    return (T[]) Array.newInstance(klass, size);
}

For example, in your case:

HashTable<Integer> t = new HashTable<Integer>();
Integer[] intArray = t.createArray(Integer.class, 4);
intArray[0] = 1; intArray[1] = 2;
intArray[2] = 3; intArray[3] = 4;

System.out.println(Arrays.toString(intArray));
> [1, 2, 3, 4]
Óscar López
  • 215,818
  • 33
  • 288
  • 367
  • 2
    This is a reflectively-created array unsafely cast to a generic type. Not sure if it will count as a generic array creation. At least it is not for me. For me the whole point is that there is no full generic type information at runtime, therefore it is not possible to instatiate a new T. – Edwin Dalorzo May 01 '12 at 14:09
  • 1
    Although this solution requires casting and warning suppression it shows a good work-around. I think that all guys here gave useful answers. `(T[])Array.newInstance()` is like `(T[])new Object[]` and like `(T[])new ArrayList().toArray()`. All these solution are "not clear" that was perfectly explained by @Amir Pashazadeh – AlexR May 01 '12 at 16:36
  • @edalorzo you're right, I added a warning at the beginning of my answer – Óscar López May 01 '12 at 17:20
  • @Alex Would't `(T[]) new Object[]` end up causing a `ClassCastException`? Because arrays are reifiable, and an array of `Object` is not array of `T` and therefore this cast could never succeed, as far as I know. If so, this cannot be the same as the suggeste answer. Neither would succed the `toArray()` method because of the same reasons. – Edwin Dalorzo May 01 '12 at 21:40
2

You could NOT create a T (in Java), but an T[] is internally the same as Object[].

public class HashTable<T> {

    private T[] array;

    @SuppressWarnings("unchecked")
    HashTable(int initSize) {
        this.array = (T[]) new Object[initSize];
    }
}

(Will compile, I checked)

Due to comments of newacct, it would be probably better just to use an Object[] and to cast the items to T.

public class HashTable<T> {

    private Object[] array;

    public HashTable(int initSize) {
        this.array = new Object[initSize];
    }

    public void put(String pKey, T pItem) {
       ...
       array[x] = pItem;
       ....
    }
    public T get(String pKey) {
       ...
       return (T) array[x];
    }
}
stefan bachert
  • 8,643
  • 3
  • 31
  • 38
  • Yes, but you have to be careful because if you have a method that returns that array as `T[]` to the outside, it will crash and there won't be any warnings. e.g. `public T[] toArray() { return array; }` – newacct May 01 '12 at 17:53
  • @newacct: I checked, you are right. However, it is still wondering me. The cast in constructor will not throw an exception. And it is legal to put any type into an Object[]. I do not see the need to throw an exception in this case – stefan bachert May 02 '12 at 07:11
  • Different array types are different classes at runtime, so if you create an `Object[]`, you cannot cast it to a `String[]`. There is no real cast in the constructor, because `T` is erased within the scope of the class. Rather, every time someone gets something from the class of type `T`, the compiler will insert a cast there to the type they expect. e.g. when somebody calls `HashTable foo = ...; String bar = foo.get("baz");` becomes erased to `HashTable foo = ...; String bar = (String)foo.get("baz");` That's why the exception occurs in the calling code. – newacct May 02 '12 at 18:17