• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Inferring type in call to generic method: how does it work?

 
Anand Kane
Greenhorn
Posts: 10
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Given below is the code that threw me into confusion; line # 30 in particular. Since both the generic parameters being passed to method 'add' are of type Shape, I assumed that for this call to method 'add', the generic type would be inferred to 'Shape'. But since it doesn't generate a class cast exception at line# 30, it is obvious that generic type is inferred as 'Object' and not Shape.

Could someone please explain the way generic types are inferred when a generic method is called?

Thanks


 
Greg Charles
Sheriff
Posts: 2984
12
Firefox Browser IntelliJ IDE Java Mac Ruby
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually, that was sort of surprising to me too, but I guess it makes sense given how Java implements generics. Generics are a late addition to the Java language and could be called a bit of a kludge in the sense that they only serve as hints to the compiler, and don't affect the resulting byte code. That is, although the basic Collection class became Collection<T> when generics were introduced, the byte codes for the two are the same. That's good because it allows older Java applications to run without modification on newer JVMs, but has some drawbacks too.

If you declare a collection to contain type ... Shape, for example ... the compiler will tell you if you try to add a non-Shape to it, and won't make you cast elements you retrieve to Shape. That's good and it saves a lot of tedious coding. However, if you try to cast a random object to type T, like this example, you won't see an error, because the runtime doesn't know what T is. It considers it to be Object, unless you specifically make T extend some other class. That exposes some weakness in Java's implementation of generics, but fortunately, it takes a fairly contrived example to do it.
 
Wouter Oet
Saloon Keeper
Posts: 2700
IntelliJ IDE Opera
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't really see the problem. The compiler is kind enough to warn us that we're using unchecked operations. And because we ignore it we get punched in the face with an ClassCastException when we try to use it.

If you don't know what caused this then read about type erasure.
Small example:
 
John Louis
Greenhorn
Posts: 10
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dear Ranchers,
Everyone seems to stick with the fact that type info in generics is lost after compilation and that at runtime its just the generic type specified to the left of the "<" that finally matters. If so, how does the following program work?



Output is: hithere and 3 as expected. How does it delegate the call to the correct method at runtime?

Regards John.

PS:- In helios, this file is not compiling. Is there a workaround for that?
 
Stephan van Hulst
Bartender
Pie
Posts: 4826
34
Chrome Netbeans IDE Windows
  • 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It doesn't. Java always decides which methods to use at compile time. The method calls are hardcoded into the program. Example:
This will print "I got an object!"
 
Wouter Oet
Saloon Keeper
Posts: 2700
IntelliJ IDE Opera
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Because at compile time it is know which method to call.
 
John Louis
Greenhorn
Posts: 10
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:It doesn't. Java always decides which methods to use at compile time. The method calls are hardcoded into the program. Example:
This will print "I got an object!"


Thanks Stephen. Do you have any idea why it doesn't get compiled in helios?
 
Rob Spoor
Sheriff
Pie
Posts: 20372
44
Chrome Eclipse IDE Java Windows
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What's the error you get? Is it perhaps the varargs on line 16?
 
John Louis
Greenhorn
Posts: 10
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob Spoor wrote:What's the error you get? Is it perhaps the varargs on line 16?


Hi Rob,
The error says:
"Method add(Collection<Integer>) has the same erasure add(Collection<E>) as another method"
and
"Method add(Collection<String>) has the same erasure add(Collection<E>) as another method"
against the 2 method definitions.
In an earlier version of eclipse, its getting compiled successfully, though I have now forgotten which version that was now.

Regards
John
 
Stephan van Hulst
Bartender
Pie
Posts: 4826
34
Chrome Netbeans IDE Windows
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's because the Java Language Specification (ยง8.4.2) says it's actually illegal.

The fact that the method to be used *can* be derived, doesn't mean it's legal. Helios has it right. Older versions do not give a compile error, while they should.
 
Vijitha Kumara
Bartender
Posts: 3908
9
Chrome Fedora Hibernate
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Helios has it right. Older versions do not give a compile error, while they should...

Not sure what the verison of JDK used by the Helios here (Or it may have added some constraints which are not enforced by the JDK even the JLS say so) ...
I don't get an error on JDK 1.6.0_07 (no IDE), have to check on another version and in the IDE too...
 
Rob Spoor
Sheriff
Pie
Posts: 20372
44
Chrome Eclipse IDE Java Windows
  • 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Because of type erasure, the methods get turned into "public int add(Collection)" and "public String add(Collection)". As you see both methods now have the same name and parameter list. Every compiler should fail compilation. If one doesn't then that compiler is actually broken.
 
Vijitha Kumara
Bartender
Posts: 3908
9
Chrome Fedora Hibernate
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob Spoor wrote:...Every compiler should fail compilation. If one doesn't then that compiler is actually broken.

Theoretically Yes, but the interesting thing is even 1.6.0_21 and 1.6.0_23 (both 64 bit) don't complain in this particular scenario...
 
Rob Spoor
Sheriff
Pie
Posts: 20372
44
Chrome Eclipse IDE Java Windows
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Apparently so. I never even knew my current compiler allows this.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic