Reputation: 213
Why is the println
printing "tom" and not showing any runtime exception after casting to List<Integer>
, while it is not able to print the value 1 after casting to List<String>
?
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String args[]) {
List list = Arrays.asList(1, "tom");
System.out.println(((List<Integer>) list).get(1));
// "tom"
System.out.println(((List<String>) list).get(0));
// ClassCastException: Integer cannot be cast to String
}
}
Upvotes: 19
Views: 1201
Reputation: 5235
This type of problem can be avoided by using generics and is the primary motivation for using generics.
This is the actual flow of your code, from your second println(
) point of view:
your code declares an ArrayList
of type Object
;
It adds an Integer
and a String
to the ArrayList
.
It cast your list to a String
list. Your list is marked as being restricted to String
.
Java generics are a compile-time feature only so your list can accepts without any problem String
and Integer
elements. The object itself knows nothing about what types it's supossed to contain unlike to the compiler.
It attemps to retreive the first element of your casted list which is supposed to be a String
and cast it to String
implicitly.
Calls println(String x)
from PrintStream
class.
But this first element is actually not a String
and is an Integer
.
You cannot cast an Integer
to a String
.
Read Generics in Java motivation section example.
Upvotes: 0
Reputation: 17
Integer i = new Integer(101);
String s = new String(i); // undefined and Invalid
StringBuffer sb = new StringBuffer(i); // defined and Valid
String s2 = "tom";
Integer i2 = new Integer(s2); //defined and valid
So when you assign a non generic list to a generic one it is assigned but when you are printing it it checks for type safety or define constructors for casting if there are valid and defined constructors then it is printed else shows class cast exception as the class can not be casted due to lack of undefined constructors for casting.
If I am wrong please help me out with the correct logic...
Upvotes: 0
Reputation: 39536
The first call of println
is statically dispatched to PrintStream.println(Object)
and the second call is dispatched to PrintStream.println(String)
. So for the second call the compiler puts an implicit cast to String
which then fails with ClassCastException
at runtime.
Upvotes: 33
Reputation: 298898
The problem here is that the java compiler picks methods at compile time, not runtime.
And at compile time it will pick the method PrintStream.print(String)
, not PrintStream.print(int)
or PrintStream.print(Object)
, both of which would succeed.
Upvotes: 3