22 January 2015

Two notes about Java Generic Types (Type Covariance and Type erasure)

Java Generics have two characteristics that are important when working with generics of Java.

The first one is the most important and most well-known than the other, the second is less known.

1. Generics types are not Covariant:

All of us knows that List<String> cannot substitute List<Object>; however String[] can substitute Object[]

This prevent error in Generics that happens in case of arrays.

String[] sArr = new String[] {"Hello"};
Object[] oArr = sArr;
oArr[0] = 10; // << Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer

However in case of Generic types, such error is being caught  at compile time, and this is because Type Parameters (Generics) doesn't allow type covariance.

Example:

List<String> sList = new ArrayList<>();
List<Object> oList = sList; // Type mismatch: cannot convert from List<String> to List<Object>

oList.add(10);

2.  Type parameters is being removed in generated byte code (Called Type erasure).

This is why you cannot say: T.class

Quote: 
When you compile some code against a generic type or method, the compiler works out what you really mean (i.e. what the type argument for T is) and verifies at compile time that you're doing the right thing, but the emitted code again just talks in terms of java.lang.Object - the compiler generates extra casts where necessary. At execution time, a List<String> and a List<Date>are exactly the same; the extra type information has been erased by the compiler.

No comments: