Here's a code snippet:
import java.util.*;
class Test
{
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>();
addToList(list);
Integer i = list.get(0); //#1 fails at run-time
String s = list.get(0); //#2 fails at compile-time
list.get(0); //#3 works fine
System.out.println(list.get(0)); //#4 works fine, prints "string"
}
static void addToList(List list){
list.add("string");
}
}
I understand why is it possible to insert an object of String class in parametrized List.
It seems like I understand why code marked with #1
and #2
fails.
But why do #3
and #4
work? As far as I understand, the compiler adds appropriate casts after type-erasure, so when I call list.get(0)
, this method should return an Object previously casted to Integer. So why there is no ClassCastException occures at #3 and #4 at run-time?
The #3 works because the object returned by get(int)
is ignored. Whatever is stored at position 0
is returned, but since there is no cast, no error happens.
The #4 works fine for the same reason: the object produced by get(0)
is treated like java.lang.Object
subclass in println
, because toString
is called. Since toString()
is available for all Java objects, the call completes without an error.
First the reason why you can add a string to a List<Integer>
. In the method
static void addToList(List list){
you use a raw type. Raw types exist purely for compatibility with older Java versions and should not be used in new code. Within the addToList
method the Java compiler does not know that list
should only contain integers, and therefore it doesn't complain when a String is added to it.
As for the different behavior of you two statements. Integer i = list.get(0)
does not fail at compile time, because Java thinks that list
only contains Integer
s. Only at runtime it turns out that the first element of list
is not an Integer, and therefore you get a ClassCastException
.
String s = list.get(0)
fails at compile time because the Java compiler assumes that list
only contains Integers, and so it assumes you try to assign an Integer to a String reference.
Just list.get(0)
does not store the result of the method call. So neither at compile time nor at run time there is any reason for a failure.
Finally, System.out.println(list.get(0))
work because System.out
is a PrintStream
and has a println(Object)
method, which can be called with an Integer
argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With