I have recently started learning Java from the basics and i run into this "little" misunderstanding about generic types, and it raised a question as follow :
Which is the difference between referencing a parameterized type instance to its raw type and using a raw type to reference another raw type instance?
I mean, which is the difference between this snippet:
ArrayList rawTypeList_NoRawInstance = new ArrayList</*Any type here*/>();
and this one:
ArrayList rawTypeList_RawInstance = new ArrayList();
Code:
import java.util.*;
public class TestGenerics{
public static void main(String args[]){
ArrayList rawTypeList_RawInstance = new ArrayList();
ArrayList rawTypeList_NoRawInstance = new ArrayList<Integer>(); /* instead of Integer could be placed any kind of type, this
* is just an example */
rawTypeList_RawInstance.add("example RawInstance"); // warning launched
rawTypeList_NoRawInstance.add("example NoRawInstance"); // same warning here
System.out.println(rawTypeList_RawInstance.get(0)); // content showed without errors/warning
System.out.println(rawTypeList_NoRawInstance.get(0)); // same here
String exampleRawInstance1 = (String)rawTypeList_RawInstance.get(0); // raw type instance compiled without error
String exampleNoRawInstance1 = (String)rawTypeList_NoRawInstance.get(0); // Generic type -Integer- instance compiled without error
Integer exampleRawInstance2 = (Integer)rawTypeList_RawInstance.get(0); // ClassCastException as expected
Integer exampleNoRawInstance2 = (Integer)rawTypeList_NoRawInstance.get(0); // same here, logically
}
}
Could anyone explain me the difference and bring me some examples about possible different consequences?
Generics are only present at compile time, they will be removed by the compiler (this is called type erasure). They are there for giving some type information to the compiler. This helps you avoiding type casts (as usual before Java 1.5) and allows the compiler for more type checking. It is also a valuable information to the programmer, for example if you see a generic type in an interface.
Without generics:
ArrayList list = new ArrayList();
So, it would make a difference if you write:
ArrayList</*Any type here*/> list = new ArrayList<>();
Now the compiler has the information what type of objects are in list
.
But this one makes no real difference to the version without generics:
ArrayList list = new ArrayList</*Any type here*/>();
The variable list has no generics information accompanied, so it is as good (or bad) as the version without generics.