0

I am just wondering, why the assignment of a wrong type value does not lead to any runtime exception. I prepared a little example, where class X holds a generic variable "object" that implements Interface A and class Y declares this generic to be of type B

public interface A{};
public class B implements A{}
public class C implements A{}
public class X<T extends A>{
  T object;
  void setObject(T t){
    object = t;
  }
  T getObject(){
   return object;
  }
}
public class Y extends X<B>{}

If I have a variable of type X holding and Y-Object, the compiler allows the assignment of any value, which is correct from my opinion. But at runtime, I would expect an exception.

public static void main(String[] args) throws Exception{
  X<A> foo = (X<A>) Class.forName("com.abc.Y").newInstance();
  foo.setObject(new B()); //should not fail
  foo.setObject(new C()); //should fail
}

I don't get any exceptions, until class Y, tries to access the object.

If I add this method to class Y, I get a ClassCastException on setObject, but I actually don't want to override all Methods with the correct Class.

public class Y extends X<B>{
  void setObject(B t){
    super.setObject(t);
  }
}
tejoe
  • 163
  • 1
  • 14

2 Answers2

2

The reason is because you're generating the object at runtime using Reflection, while generics are only checked at compile time.

This is due to Java Generics being implemented using type erasure. That is, they're not present in the compiled code.

Powerlord
  • 87,612
  • 17
  • 125
  • 175
  • thank you never heard about so far. In the decompiled code I was able to see it. – tejoe Apr 02 '15 at 19:58
  • Incidentally, if you use a normal constructor instead of reflection, the compiler should catch that the type is wrong. – Powerlord Apr 02 '15 at 20:04
1

The reason for that behavior is java's type erasure. Type erasure generally means that all generics are replaced by casting by java (that's why you get ClassCastException). So this:

List<String> list = new ArrayList<String>();
list.add("text");
String x = list.get(0);

will be converted to this:

List list = new ArrayList();
list.add("text");
String x = (String) list.get(0);

You can read more about this here: http://en.wikipedia.org/wiki/Generics_in_Java#Problems_with_type_erasure

Eyal
  • 1,748
  • 2
  • 17
  • 31