Can someone please explain to me how the compiler does not complain in the first casting, but does complain in the second?
interface I1 { }
interface I2 { }
According to JLS 5.5.1 - Reference Type casting, the rule(s) apply:
If T is a class type, then either |S| <: |T|, or |T| <: |S|. Otherwise, a compile-time error occurs.
I2 y = (I2)o3; //compiler complains here !!
In this case, an Integer and I2 are unrelated in any way, so a compile-time error occurs. Also, because Integer is final, there is no relation between Integer and I2.
I2 and I1 can be related due to both being a marker interface (there are no contract).
As for the compiled code, the rule follows:
S is o1 and T is I2.
Hope this helps.