I have this class:
class MyClass<N extends Number> {
N n = (N) (new Integer(8));
}
And I want to get these outputs:
System.out.println(new MyClass<Long>().n);
System.out.println(new MyClass<Long>().n.getClass());
Output of first
System.out.println()statement:8Output of second
System.out.println()statement:java.lang.ClassCastException: java.lang.Integer (in module: java.base) cannot be cast to java.lang.Long (in module: java.base)
Why do I get the first output? Isn't there a cast as well? Why do I get the exception in the second output?
PS: I use Java 9; I tried it with the JShell and I got an exception on both outputs. Then I tried it with IntelliJ IDE and got the first output but the exception at the second.
The behavior that IntelliJ shows is clear to me:
You have an unchecked cast in
MyClass. This meansnew Integer(8)is not immediately cast toLongbut to the erasureNumber(which works), when this line is executed:N n =(N)(new Integer(8));Now let's look at the output statements:
boils down to
String.valueOf(new MyClass<Long>().n)->((Object)new MyClass<Long>().n).toString()which works fine, because n is accessed throughObjectand also thetoString()method is accessed through static typeObject-> no cast toLongoccurs.new MyClass<Long>().n.toString()would fail with an exception, becausetoString()is tried to be accessed via static typeLong. Therefore a cast of n to typeLongoccurs which is not possible(Integercan't be cast toLong).The same thing occurs when executing the 2nd statement:
The
getClassmethod (declared inObject) of typeLongis tried to be accessed through static typeLong. Therefore a cast of n to typeLongoccurs which yields a cast exception.JShell behavior:
I tried to reproduce the resulting exception for the first output statement on JShell - Java 9 early access Build 151:
But it seems that JShell gives the exact same results as IntelliJ.
System.out.println(new MyClass<Long>().n);outputs 8 - no exception.