Reading Type From Unbounded Wildcard
Unbounded wildcard<?> is really just a wildcard with a bound of type Object <? extends Object>. Obviously, even an unbounded wildcard instantiation holds objects that can be assigned to Object, so it’s OK to read an unbounded wildcard as the Object type :
Our instantiation g1 returns type is Object. Our instantiation g2 returns type is A because GenTwo type parameter bounded by A(T extends A). But, of course, we cannot know the actual type of the elements, so we cannot write to the list through our unbounded wildcard type :
class A { int a; A(int aa) { a = aa; } } class B extends A { int b; B(int aa, int bb) { super(aa); b = bb; } } class C extends B { int c; C(int aa, int bb, int cc) { super(aa, bb); c = cc; } } class GenOne<T> { T t[]; GenOne(T tt[]) { t = tt; } T getSpecifiedType(int i){ return t[i]; } } class GenTwo<T extends A> { T t[]; GenTwo(T tt[]) { t = tt; } T getSpecifiedType(int i){ return t[i]; } } public class Javaapp { public static void main(String[] args) { GenOne<?> g1 = new GenOne<A>(new A[]{new A(10),new B(20,30),new C(40,50,60)}); Object ob1 = g1.getSpecifiedType(0); Object ob2 = g1.getSpecifiedType(1); Object ob3 = g1.getSpecifiedType(2); GenTwo<?> g2 = new GenTwo<A>(new A[]{new A(10),new B(20,30),new C(40,50,60)}); A a1 = g2.getSpecifiedType(0); A a2 = g2.getSpecifiedType(1); A a3 = g2.getSpecifiedType(2); } }