javagenericsraw-types

How raw type works in Java?


I'm learning about generics and I have a misunderstanding.

For example I have this simple code:

import java.util.ArrayList;

public class DemoApp {

    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(1);
        System.out.println(list.get(0).getClass().getName()); 
        int value = (Integer) list.get(0);
    }
}

I don't understand why should I cast the list.get(0) to Integer because this statement System.out.println(list.get(0).getClass().getName()); has this result java.lang.Integer?

If I use this statement int value = list.get(0); I get this error: Type mismatch: cannot convert from Object to int... and I really don't understand, is list.get(0) an Object or an Integer?


Solution

  • The list.get(0).getClass().getName() will access an element in the List, and find out at runtime that it's indeed an integer. It could be anything else, though.

    What the compiler knows at compile time is that your list contains items of type Object, see the signature of List.get(int). So it can't prove that int value = list.get(0) would always be correct. You have to explicitly cast.

    The whole generics thing in Java is compile-time only. It's a way to tell the compiler how to limit type-parametrized classes only to particular types, and thus guarantee at compile time that operations on them are indeed correct. That is, the compiler won't allow you to put a String into a List<Integer>.

    In runtime, the type parametrization information is erased. The JVM operates on by relying on the compiler having done the job of generating correct code. There's nothing at runtime that allows the JVM to know what type the content of a List is; ArrayList has a single implementation for any class parameters. (This is unlike C# or C++.)