Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic Array Creation

Here is the code I'm using

public class aClass<T> {

    private T[] elements;

    public aClass(T[] elements) {
        this.elements = elements;
    }

    public void doSomething() {
        T[] newArray = (T[]) new Object[5];
        ...
    }

}

I've seen people saying that creating an array like this is a bad idea, due to it being not type safe. However, every time I use it, I have no problems with it. When would creating an array like this cause a problem?

Thanks

like image 901
Stripies Avatar asked Apr 05 '12 15:04

Stripies


People also ask

Can you make a generic array?

Generic array creation is not allowed in Java. Hope this helps!! If you need to know more about Java, join our Java certification course online.

How do you create an array in generic class?

Creating Generic Arrays in Java To get around this, you can create an Object array and cast it, like this: E[] myGenericArray=(E[])new Object[128];

What is generic array creation error Java?

Invariant: It means you cannot assign subclass type generic to its super class generic reference because in generics any two distinct types are neither a subtype nor a supertype. For instance, List<Object> objectList = new ArrayList<Integer>(); // won't compile.

Can we have generic array in Java?

Java allows generic classes, methods, etc. that can be declared independent of types. However, Java does not allow the array to be generic. The reason for this is that in Java, arrays contain information related to their components and this information is used to allocate memory at runtime.


2 Answers

Here is an example that causes issues:

public class Main {

    public static class List<E extends Number> {

        private E[] myE;

        public void hello(E e) {
            E[] newArray = (E[]) new Object[5];
            for (int i = 0; i < newArray.length; i++) {
                newArray[i] = e;
            }
            myE = newArray;
        }

    }

    public static <T> T[] createArray(int size) {
        return (T[]) new Object[size];
    }

    public static void main(String[] args) throws IOException {
        List<Integer> integers = new List<Integer>();
        integers.hello(5);
    }
}

Your code works because when you declare your generic parameter <T> it is unbound, meaning that it extends Object. When you cast your array to (T[])you are actually casting to (Object[]) because that is the best the compiler can do. Now, if you keep your array inside your code, you should not have too many problems. But if somebody outside your code can retrieve that array and has instantiated your class with a type other than object, he will have ClassCastException.

like image 155
Guillaume Polet Avatar answered Oct 27 '22 20:10

Guillaume Polet


You cannot create an array of T because Java does not know, at run time what is the type of T. This is due to the fact that in Java generics is implemented with type erasure. This means that the compiler discards most of the generic type information after ensuring everything is Ok.

With arrays the story is different, because Java needs to know the exact type of T in order to create the given array, and since such thing cannot be determined you cannot create an array of a generic type.

What you can do is to provide a instance of the actual array that you want to use, and the Java compiler can ensure it is of the appropriate type:

public static <T> void fillWith(T[] destiny, List<? extends T> source){
    for(int i=0; i<= destiny.length; i++){
        destiny[i] = source.get(i);
    }
}

The java.utils.Arrays.copy method offers an alternative carefully using generics and reflections that you can use as a reference for what you want to do.

public static <T> T[] copyOf(T[] original, int newLength) {
   return (T[]) copyOf(original, newLength, original.getClass());
}


public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
}
like image 39
Edwin Dalorzo Avatar answered Oct 27 '22 18:10

Edwin Dalorzo