Generic programming concepts may have different implementations. In Java programming language generic type information is erased during compilation to ensure binary compatibility.
This means that at runtime all these objects will have the same type:
// Raw type
List list = new List();
// Generic types
List<Integer> list1 = new List<>();
List<String> list2 = new List<>();
Java Language Specification defines type erasure as following:
- The erasure of a parameterized type G<T1,...,Tn> is |G|
- The erasure of a nested type T.C is |T|.C
- The erasure of an array type T[] is |T|[]
- The erasure of a type variable is the erasure of its leftmost bound
- The erasure of every other type is the type itself
It's very useful to remember these rules to be able to see the structures you use in your code from the perspective of Java Virtual Machine that works with bytecode and lacks information that was erased during compilation step.
Type erasure greatly influences the design of Java programming structures including Java Standard Library. Let's look at the signature of Collection.toArray method:
You may imagine that the main purpose of an array passed as an argument is here for memory allocation and performance reasons, but its main task is to provide type information at the runtime. Remember that due to type erasure the code:<T> T[] toArray(T[] a)
Collection<Integer> col = new ArrayList<Integer>();
Integer[] array = col.toArray(new Integer[]);
Collection col = new ArrayList();
// col have no type parameter information at runtime. What array type should we create inside toArray() method without a parameter?
Integer[] array = col.toArray();
So, it's perfectly fine to call this method in a way:
Remember what type information is available in runtime when designing your own APIs!Collection<Integer> col = ... whatever // toArray will create array of appropriate size Integer[] array = col.toArray(new Integer[0]);