Downcasting a subclass of a concrete generic
Hi--
Been puzzling over this one for quite awhile, and I still can't figure it out. I'm trying to downcast a generic type to a subclass of a concrete type. Now admittedly that's messy and I'd like to refactor, but I'm still puzzled. Take the following code:
publicclass Test1<T>{
protectedfinal T obj;
public Test1(T obj){
this.obj = obj;
}
publicstaticvoid main(String[] args){
Test1<?> testObj =new Test2("hello");
System.err.println("Calling a method: " + ((Test2) testObj)).aMethod());
}
}
publicclass Test2extends Test1<String>{
public Test2(String obj){
super(obj);
}
public String aMethod(){
return obj;
}
}
This fails to compile, saying that Test1<capture of ?> isn't convertible to Test2.
Now suppose I change to the following:
publicclass Test1<T>{
protectedfinal T obj;
public Test1(T obj){
this.obj = obj;
}
publicstaticvoid main(String[] args){
Test1<?> testObj =new Test2<String>("hello");
System.err.println("Calling a method: " + ((Test2) testObj).anotherMethod());
}
}
publicclass Test2<Textends String>extends Test1<T>{
public Test2(T obj){
super(obj);
}
public String anotherMethod(){
return obj;
}
}
Here all I've done is add a parameter to the Test2 type that gives the same information available in item 1. In this case, however, it compiles and runs fine.
Even more oddly, the following also works and does not produce any warnings:
publicclass Test1<T>{
protectedfinal T obj;
public Test1(T obj){
this.obj = obj;
}
publicstaticvoid main(String[] args){
Test1<?> testObj =new Test2("hello");
System.err.println("Calling a method: " + ((Test2) ((Test1) testObj)).anotherMethod());
}
}
publicclass Test2extends Test1<String>{
public Test2(String obj){
super(obj);
}
public String anotherMethod(){
return obj;
}
}
So essentially the system is ok as long as I cast the generic type to a raw type, and then downcast to the subclass of the concrete type... but I can't do the cast directly?
My feeling is that Java is being a little overly touchy about trying to prevent casting to a concrete type-- in the case where the type you're trying to cast to is itself not generic, shouldn't that be allowed? Or am I missing something subtle about how the generics work?

