Array of Wildcards
In general, wildcard instantiations of generics can be used as the base type for arrays in the same way that concrete instantiations can. For example:
The first statement declares an array of unbounded wildcard instantiations of Gen. Each element of the array can hold an instance of the wildcard type, meaning in this case that each element of the array could hold a different instantiation of Gen. Generally Java won’t let us create arrays of generic types, there is an exception to the rule. Java does allow us to create arrays of unbounded wildcard instantiations. Why does this work? Because each element in the unbounded wildcard instantiation of the array can hold any instantiation, no runtime check of the generic portion of the type is necessary at runtime. Any instantiation of Gen is assignable to the element of type Gen<?>, so only the check of the raw type is required.
Reading and Writing Through the Unbounded Wildcard Instantiation
Generally, we cannot read the object as any specific type from the unbounded wildcard instantiation. Because the compiler cannot know the actual type of the elements:
But we can read the object type as the upperbound of the type parameter of that class. So, we can always read the type as Object through our unbounded wildcard instantiation. The type Object is the default upper bound:
What about writing? we cannot write the object as any specific type to the unbounded wildcard instantiation. We can’t call the setT() method while the reference stored in anygen[index] is of type Gen<?> because the compiler cannot know the actual type of the elements:
You must cast the reference to a specific type to allow the setT() and getT() methods for that type to be called:
In this case, you get two warnings from the compiler from the statements that involve explicit casts because the compiler cannot verify that this cast is valid. If it isn’t, calling the setT() method causes an exception to be thrown at run time so you have to accept responsibility for it. Note that you can create arrays of a generic type only using a wildcard specification that is unbounded. If you specify an upper or lower bound for a wildcard type argument when defining an array type, it is flagged by the compiler as an error. For example:
Program
Program Source
class Gen<T> { private T t1; Gen(T t) { t1 = t; } void setT(T v) { t1 = v; } T getT() { return t1; } } public class Javaapp { public static void main(String[] args) { Gen<?> anygen[] = new Gen<?>[3]; anygen[0] = new Gen<Integer>(50); anygen[1] = new Gen<String>("Java"); anygen[2] = new Gen<Float>(23.5f); ((Gen<Integer>)anygen[0]).setT(100); Integer in = ((Gen<Integer>)anygen[0]).getT(); System.out.println("anygen[0].getT() -> "+in); } }