Java generics uses Types. If you are not still using java generics, following example code explains you a simple generics usage:
package com.sample;
import java.util.HashMap;
import java.util.Map;
public class TypeErasure {
public static void main(String args[]) {
Map<String, String> languageMap = new HashMap<String, String>();
languageMap.put( "1954" , "FORTRAN" );
languageMap.put( "1958" , "LISP" );
languageMap.put( "1959" , "COBOL" );
String language = languageMap.get( "1954" );
System.out.println( "Our favourite language is " +language);
}
}
|
In the above code, we instantiate a map saying that the key and
values will be String. These are type parameters. It provides you type
safety.
Type erasure is a process to remove the types and map it to byte
code. Just trying to give a formal definition for type erasure ;-) Type
erasure happens at compile time. Java compiler removes those generic
type information from source and adds casts as needed and delivers the
byte code. Therefore the generated byte code will not have any
information about type parameters and arguments. It will look like a old
java code without generics. You want to have a look at it?
Compile above given source and get a class file. Then de-compile that
generate class file and you will know what is inside. You may use JAD
to de-compile. Else you can avoid the round trip and use the JDK itself
directly on java source and find out how the compiled source will look
like.
javac -XD-printflat -d .java
package com.sample;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;
public class TypeErasure
{
public TypeErasure()
{
}
public static void main(String args[])
{
Map languageMap = new HashMap();
languageMap.put( "1954" , "FORTRAN" );
languageMap.put( "1958" , "LISP" );
languageMap.put( "1959" , "COBOL" );
String language = (String)languageMap.get( "1954" );
System.out.println(( new StringBuilder( "Our favourite language is " )).append(language).toString());
}
}
|
You should note two things in the above de-compiled code.
- First thing is, “<String, String>” is missing.
- Second thing is (String)languageMap.get(“1954″) a type cast is added.
This is done by the java compiler while compiling java source code to byte code. This process is called java type erasure.
Main reason behind having type erasure at compile time is to give
compatibility with old versions of java code where you don’t have
generics. If you look at the definition of Map intereface using source
available in JDK (beyond 1.5 ), it will be like
public interface Map<K,V> {
|
So if you use the Map without generics that should work with latest
code. Thats why the java type erasure is brought in. When you use
generics compiler checks whether you use all you type properly or not.
If something is wrong you get an error at compile time and you need not
wait until run time and blow up your production.
Consequences of Type Erasures
A java class with parametrized type cannot be instantiated as it
requires a call to constructor. At run-time the type is not available
because of type erasure and the instantiation cannot be done.
T instantiateElementType(List<T> arg)
{
return new T();
}
|
Because of type erasure, at run-time you will not be able to find out
what was the predefined type. There are hacks available using
Reflection, but it is not guaranteed that it will work in all cases. It
is also not a formal way.
There is lots of discussions on whether you need type erasure or is
it implemented in a good way is going around. Leave that aside. If you
use java, its better to use generics as much as possible. Advantage you
get in using generics is type safety and clarity in your code. Though
type erasure is good or bad, better know about it. Because it is the one
that translates your generic java code to byte code.
0 comments:
Post a Comment