GeeCON Prague 2014*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Question on type erasure. (just another generics question) Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Question on type erasure. (just another generics question)" Watch "Question on type erasure. (just another generics question)" New topic
Author

Question on type erasure. (just another generics question)

Florin Florentin
Ranch Hand

Joined: May 12, 2009
Posts: 43
Hello. I have a question about overloading / type erasure.

The following code compile and runs. I think (that's only my opinion, so if i'm not right i would love to be corrected) because T it's erased in the second function to String, and in the first it is erased to Object, so there are different arguments.




The following code isn't compiling. It's saying that the methods have the same erasure t1(List<T>).



Why is in the list example a different behavior?
Chad Michaels
Ranch Hand

Joined: Jun 25, 2010
Posts: 42
Interesting. I have no idea, but I'd like to guess.

I think it's basically because in one example, both parameters are different:
public <T> void t1(T t1) { } // T can be any object
public <T extends String> void t1(T t2){ } // T can only be String, or a subclass

And, in the other example which causes a compiler error, both parameters are the same:
public <T> void t1(List<T> t1) { } // One list parameter
public <T extends String> void t1(List<T> t2) { } One list parameter

In fact, you get the same compiler error by just:
public void t2( List< String > x ) { }
public void t2( List< Integer > x ) { }

Again, that's just a guess, and I'm probably wrong. You're probably right, it has something to do with erasure. I would like to know the correct answer myself.
Florin Florentin
Ranch Hand

Joined: May 12, 2009
Posts: 43
I would like more opinions
Dieter Quickfend
Bartender

Joined: Aug 06, 2010
Posts: 543
    
    4

<T extends String> can only be a String. Don't forget String is final. So for Strings, it will use that method. For anything else, it will use another.

As before said, the List parameter is the same parameter. List<Integer> and List<String> is both the same class, so it's not a legal overload.


Oracle Certified Professional: Java SE 6 Programmer && Oracle Certified Expert: (JEE 6 Web Component Developer && JEE 6 EJB Developer)
Wouter Oet
Saloon Keeper

Joined: Oct 25, 2008
Posts: 2700

It doesn't matter that in the example String was used. It can be replaced with (almost) everything.

The first part is compiled to:
public void t1(java.lang.Object);
Code:
0: return

public void t1(java.lang.String);
Code:
0: return

The second part will not compile because of the name clash due to type erasure. The type erasure will (simply put) convert the methods to something like this:
public void t1(List) { }
public void t1(List){ }


"Any fool can write code that a computer can understand. Good programmers write code that humans can understand." --- Martin Fowler
Please correct my English.
Florin Florentin
Ranch Hand

Joined: May 12, 2009
Posts: 43
Thank you for the answer.

Wouter Oet wrote:

The second part will not compile because of the name clash due to type erasure. The type erasure will (simply put) convert the methods to something like this:
public void t1(List) { }
public void t1(List){ }



Why doesn't it is compiled to :

public void t1(List<java.lang.Object>) { }
public void t1(List<java.lang.String>){ }

?
Yves Caron
Greenhorn

Joined: Jul 01, 2010
Posts: 3
Why doesn't it is compiled to :

public void t1(List<java.lang.Object>) { }
public void t1(List<java.lang.String>){ }

?


Consider this first example:



Before the compiler erases the type information, List<Object> and List<Number> are two different types and the compiler will force you to use the correct type.

After the compiler has done all of its verifications, it erases the type information.

After the compiler erased the type information, List<Object> and List<Number> both become the same type which is List.

Both methods end up with the same signature:
public void t2(List objects) { }
public void t2(List numbers) { }

The result is a name clash.

Compare this with the second example:



You can substitute any type whatsoever, in the end, the compiler will erase it and the type will be List just as it did in the first example.

Here is a last example:



Now compare the methods t1 from Example02 and Example03. The compiler does not find a name clash but it reports that <O>t1(O) is already defined. You can only conclude that <O>t1(O) and <N extends Number>t1(N) are two different method signatures. From your comments, you had already understood that part.

Take care.
Florin Florentin
Ranch Hand

Joined: May 12, 2009
Posts: 43
Sorry for the late response. I was away a couple of days.

Thank you for your answers, but i want to know why it's this behaviour.
Dieter Quickfend
Bartender

Joined: Aug 06, 2010
Posts: 543
    
    4

It's all about the method signature. In the first example, it's a legal overload, because basically, <T extends Object> is not the same as <T extends String>. The compiler will know which method to use, namely the second if it's a String, the first if it's anything other than a String.

In the second example, with the Lists, because lists have no type at Runtime, you're basically calling "public void t1(List t2){}" twice, which is the same method signature at runtime and not a legal overload.

Florin Florentin
Ranch Hand

Joined: May 12, 2009
Posts: 43
Is it then correct to afirm that when using generics, type information is erased to it's first bound, except list, where type information is erased to the raw type?

Shanky Sohar
Ranch Hand

Joined: Mar 17, 2010
Posts: 1051

PLease keep this in mind that all the generics type information is erased at compile time
So at runtime collection are collection like earlier days


SCJP6.0,My blog Ranchers from Delhi
Dieter Quickfend
Bartender

Joined: Aug 06, 2010
Posts: 543
    
    4

Florin Florentin wrote:Is it then correct to afirm that when using generics, type information is erased to it's first bound, except list, where type information is erased to the raw type?

Something like that, I believe.

In the second case with the Lists, the signature the method will use is determined, type will be erased, and at runtime, the signature will be called but there will be two methods with the same identical signature in that class. So I'd say since the compiler needs to be certain about generics due to type erasure, it won't allow two methods which will resolve to the same signature at runtime, because even though the signature the program will use is determined at compile time, the actual method will be called only at runtime (see overriding/overloading), which would compromise type safety.


However, I think I'll go dig a little deeper into Generics again.

Good question!
 
GeeCON Prague 2014
 
subject: Question on type erasure. (just another generics question)