Type erasure is the technique using which the Java compiler translates generic / parameterized type to raw type in Java generics. Type erasure is applicable in the context of generics. Following example illustrates a simple usage of generics in Java.
package com.javapapers.java.generics; import java.util.HashMap; import java.util.Map; public class TypeErasure { public static void main(String args[]) { MapgenericsMap = new HashMap (); Map noGenericsMap = new HashMap(); genericsMap.put("1954", "FORTRAN"); String language = genericsMap.get("1954"); System.out.println("Language: "+language); } }
In the above code, we instantiate a generic map using the parameterized type as String for generic type. It provides us the type safety and helps avoid the need for explicit casting.
Type erasure is a process to remove these types and map it to raw type in byte code and it is done during compilation by the Java compiler. You can take this as a near formal definition for type erasure. Java compiler replaces generic type information from source and adds casts as needed and delivers the byte code, generics related information are kept as meta-data in the bytecode for debugging, reflection purposes. With respect to general runtime execution, code will look like plain Java without generics.
Let us compile the above given Java source file and get a binary class file. Then de-compile that generated class file and inspect what type erasure has done. You may use any Java decompiler of your choice. For now the javap utility is sufficient for this simple inspection purpose. First compile the source and get a Java class file. Then run the command “javap -c TypeErasure“. Here TypeErasure is the name of the Java class.
C:\Users\Cycle\Desktop>javap -c TypeErasure Compiled from "TypeErasure.java" public class TypeErasure extends java.lang.Object{ public TypeErasure(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: new #2; //class java/util/HashMap 3: dup 4: invokespecial #3; //Method java/util/HashMap." ":()V 7: astore_1 8: new #2; //class java/util/HashMap 11: dup 12: invokespecial #3; //Method java/util/HashMap." ":()V 15: astore_2 16: aload_1 17: ldc #4; //String 1954 19: ldc #5; //String FORTRAN 21: invokeinterface #6, 3; //InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; 26: pop 27: aload_1 28: ldc #4; //String 1954 30: invokeinterface #7, 2; //InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object; 35: checkcast #8; //class java/lang/String 38: astore_3 39: getstatic #9; //Field java/lang/System.out:Ljava/io/PrintStream; 42: new #10; //class java/lang/StringBuilder 45: dup 46: invokespecial #11; //Method java/lang/StringBuilder." ":()V 49: ldc #12; //String Language: 51: invokevirtual #13; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 54: aload_3 55: invokevirtual #13; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 58: invokevirtual #14; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 61: invokevirtual #15; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 64: return }
Note two things in the above de-compiled code,
This is done by the java compiler while compiling java source code to byte code as part of the process java type erasure. Main reason behind having generics and type erasure is to give the programmer ability to write generic code and type safety. Generics is not forced, the generic type can be directly used as raw type instead of supplying parameterized type argument. But it is not a good coding practice.
At run-time the generic type is not available in general scenario, that’s what the type erasure does. There are scenarios where people accessing the generic type using reflection or non-java API.
T instantiateElementType(Listarg) { return new T(); //causes a compilation error }
Basics of Generics will help us understand that ‘T’ is just a placeholder here and type erasure will remove it during compilation. Generics and type erasure is good for a programmer. Advantage we get in using generics is type safety and clarity in code, so embrace it.
Comments are closed for "Type Erasure".
Good analysis….
Hi,
Interesting blog you got. This is like a haven for java devs! I blog about Java too but with all other technologies. Anyway, nice article about type erasures. I haven’t really heard of this yet and I need sometime to absorb all that I’ve read so far…
good catching………..
Nice catch there , hence i can not see with someone bother use type erasure as a programming technique instead of generics , only use i know of type erasure is to maintain binary compatibility with Java libraries and applications that were created before generics.
Keep up the good work mate !
BTW2, you can very easily test this without resorting to JAD decompilation.
Just make a class with a method that accepts of returns a generic type. That might even be a private method:
import java.util.LinkedList;
import java.util.List;
public class GenericList {
public static void main(String[] args) {
List<Number> numberList = new LinkedList<Number>();
numberList.add(Integer.valueOf(3));
numberList.add(Long.valueOf(Long.MAX_VALUE));
printList(numberList);
}
private static void printList(List<? extends Number> printedList) {
System.out.println(“List: ” + printedList);
}
}
Compile the class:
javac GenericList.java
Have a look at its contents:
$ hexdump -C GenericList.class | less -in
What you’ll see:
….
000000b0 73 74 01 00 13 28 4c 6a 61 76 61 2f 75 74 69 6c |st…(Ljava/util|
000000c0 2f 4c 69 73 74 3b 29 56 01 00 09 53 69 67 6e 61 |/List;)V…Signa|
000000d0 74 75 72 65 01 00 28 28 4c 6a 61 76 61 2f 75 74 |ture..((Ljava/ut|
000000e0 69 6c 2f 4c 69 73 74 3c 2b 4c 6a 61 76 61 2f 6c |il/List;)V.|
….
Where did that java/lang/Number come from?
If type erasure really did remove the generic information from compiled class file, there would be no mention of java.lang.Number as it exists only in generic declarations in the source! As you can see, the exact information about printList() method’s generic argument is placed in the “Signature” section of the class file.
See also the official specification of Java class file format, section 4.4.4:
http://java.sun.com/docs/books/vmspec/2nd-edition/ClassFileFormat-final-draft.pdf
“4.4.4 Signatures
Signatures are used to encode Java programming language type information that is
not part of the Java virtual machine type system, such as generic type and method
declarations and parameterized types. See The Java Language Specification, Third
Edition, for details about such types.
This kind of type information is needed to support reflection and
debugging, and by the Java compiler.”
Cool Site :-)
It’s good to read in this site..
Im going to prefer this to my friends!!
nice explanation for type erasure, superb answer
It really helps me to understand about type erasure with the generics example.
Really nice job :)
Can you explain Java Generics more in Detail in your next post?
hi,
This type erasure is nice concept,At first time i heard in this . I like this subject very much .Thanks for guide.
nice article
Obviously this is the best place to learn what Type Erasure is.. Thanks a lot
nice article,thanks:)
[…] bridge method is a synthetic method created during type erasure. Let us see see about bridge method is a detailed separate […]
My question is :
BottomLine Do we have to use type erasure or not…because why one should decompile the class again & then use it…
an u give me a real life example where one should use it…
I like your post.
Great helps and this article is good.
Kapil,
Type erasure is done by the Java compiler. We as a programmer got to use generics and that it. We are not doing anything explicitly for Type erasure. It is done during compilation process. You got to read the tutorial line by line. :-)
Welcome Arun.
welcome Sathiya.
Yes I am writing a series on Java Generics:
https://javapapers.com/core-java/java-generics-introduction/
https://javapapers.com/java/java-generics-basics/
and continuing…
Thanks John.
Thanks Pinoy, you too have got a nice blog.
Thanks Hoque.
The point that, “the complete generic information is not erased” is right and I agree with that. Information related to generics are retained as meta information in class file. Thanks Olo, I have updated the tutorial above.
But erasure happens during runtime is wrong, it happens during compile time.
Thats fine. Yes thats right, type erasure does not completely erase the generics information and it retains type information as meta-data in binary class.
This is one of the reasons why Java has so much hate attached to it. Unfortunately it could of been a good language but due to the little things like type erasure, it has become a target of hate.
[…] the compiler translates the generics type information to raw types and this process is called type erasure. That is the type parameter like <T> are replaced by the left most bound type and in case if […]