Search code examples
javagenericsraw-typesparameterized-types

Why is it possible to get back an object of "incorrect-type" from the parametrized List in Java?


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?


Solution

  • 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.