What Is the Concept of Erasure in Generics in Java

What is the concept of erasure in generics in Java?

It's basically the way that generics are implemented in Java via compiler trickery. The compiled generic code actually just uses java.lang.Object wherever you talk about T (or some other type parameter) - and there's some metadata to tell the compiler that it really is a generic type.

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.

Compare this with, say, C#, where the information is retained at execution time, allowing code to contain expressions such as typeof(T) which is the equivalent to T.class - except that the latter is invalid. (There are further differences between .NET generics and Java generics, mind you.) Type erasure is the source of many of the "odd" warning/error messages when dealing with Java generics.

Other resources:

  • Oracle documentation
  • Wikipedia
  • Gilad Bracha's Java generics guide (PDF - highly recommended; link may need to change periodically)
  • Angelika Langer's Java Generics FAQ

How Type Erasure work in java?

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. There is no way to determine the value of T at runtime, because that information is removed before the code is compiled.

Java type erasure with generic methods

Generics are opt-in (because they were added in Java 5, and old code still needs to work).

ClassB sampleB1 = new ClassB();  // this is a raw type

When you opt-out by using raw types you won't get any of the features, including generic type inference (your <T> on the method will just be ignored). You will get a compiler warning about better not using raw types instead.


What does method return type <T> has to do with <O>?

Nothing. You declared <T> on the method, it is only visible for that method, it is completely unrelated to the O on the class (unless you did something like <T extends O>) and it could even shadow other things (you could call it <O> as well, or even <String> -- but don't do that).

Java - What's the difference between type erasure and type inference?

Both of them serve completely different needs:

Type erasure is like you said and is needed because java byte code is not generic hence you need to remove the typing. This isn't a feature that helps you code it's just an automatic compile time change that has to happen for the jvm to understand your code.

Type inference on the other hand is the compiler being "smart" and knowing what type you were referring to even though you didn't actually write it. Just like in your example the compiler knows that Box<>() actually means Box<String>() and lets you continue coding with type safety as if you wrote Box<String>. This way you can write less verbose code and the compiler would still understand it.

You can understand from all of this that generics in Java are actually mostly a compile time thing that lets you code with more safety and helps you find errors in compile-time rather than run-time.

Generics type erasure in Java

Since my first exposure to generics was with C# , it took time get a hold of what type erasure is in java.

But after better understanding java generics , i realized that in my question i'm mixing 2 separate topics : Generics and Reflection.

The main question was , why did the second call here

 System.out.println(g.getClass());
System.out.println(g.ob.getClass());

returned java.lang.Integer instead of java.lang.Object.

Looking at the docs for getClass() , the answer becomes obvious

Returns the runtime class of this Object.

so, getClass() doesn't return the type of reference but the actual object being referred to by the reference.

For ex :

Object o =  "abc";
System.out.println(o.getClass());

The output wouldn't be the type of the reference java.lang.Object but rather the actual type of the object java.lang.String.



Related Topics



Leave a reply



Submit