There's nothing wrong with the type T[]
itself. It's perfectly fine to have a variable of type T[]
and you can assign any value of type T[]
to that variable fine, without any warnings. The question is how do you get a value of type T[]
.
I think you've answered your own question later when you showed that, for example, you can have a value of type T[]
passed in from the outside, into a method (or a constructor) of your class. And in the caller's scope in your example, T
is a concrete type (Integer
), so the caller can create a T[]
in its scope fine and pass it in.
As you have found, you can't create a value of type T[]
(other than null
) without a warning inside the class (where T
is generic). This is because arrays know their component type at runtime (because arrays in Java check at runtime every element that is stored into the array is an instance of the component type), so to create an array object, you need to provide the component type of the array you want to create at runtime, and inside the class, you don't know what T
is at runtime. So new T[5]
is not a valid expression.
In Andreas's answer, they create an array of type Object[]
, and then cast it to T[]
, but this is basically lying to the compiler. Obviously, if T
is any type other than Object
, this cast is incorrect. For example, String[] foo = (String[]) new Object[5];
throws a class cast exception at runtime. However, T
is erased to Object
inside the class, so it does not immediately throw a class cast exception. You get an unchecked cast warning to warn you that you might not get an exception even if the cast is incorrect, so you may have a variable whose compile-time type is incompatible with its runtime type, and you may unexpectedly get a class cast exception somewhere else later. For example, if you have a method that returns the array to the outside of the class as type T[]
, and the place outside the class has a concrete type for T
, it will cause a class cast exception where there is no cast:
public class Example<T> {
private T[] array = (T[]) new Object[5];
public T[] getArray() {
return array;
}
public static void main(String[] args) {
Example<Integer> example = new Example<>();
Integer[] foo = example.getArray(); // class cast exception
}
}
Your statement that you cannot store any value in the array is incorrect. You can store values in it, but you can only store values of type T
. Inside the class, you don't know what T
is, so where are you going to get a value of type T
? You would either have to use null
, or you have to get it from outside the class:
public class Example<T> {
private T[] array;
public Example(T[] a) {
array = a;
}
public void set(int i, T x) {
array[i] = x;
}
public static void main(String[] args) {
Example<Integer> example = new Example<>(new Integer[5]);
example.set(0, 1);
}
}