Type Erasure and Overloading in Java: Why does this work?

java, overloading, type-erasure

Solution

Consider the following 4 methods

           Java code                        bytecode

m1:    Byte f(List<Byte> list)           f List -> Byte
m2:    Long f(List<Byte> list)           f List -> Long
m3:    Byte f(List<Long> list)           f List -> Byte
m4:    Long f(List<Long> list)           f List -> Long

According to the current Java Language Spec,

m1 and m2 cannot coexist, nor can m3 and m4. because they have the same parameter types.

m1 and m3 can coexist, so can m1 and m4. because they have different parameter types.

But javac 6 only allows m1+m4, not m1+m3. That's related to the bytecode representation of methods, which includes return types. Therefore, m1+m4 are ok, but not m1+m3.

This is a screwup where Java and JVM specs don't see eye to eye. There is no "correct" way for javac.

While it sucks, the good news is, overloading is a vanity, not a necessity. We can always use different, more descriptive and distinct names for these methods.

Problem

I have the following code: ``` public class Pair< T, U > { public T first; public U second; } public class Test { public int method( Pair< Integer, Integer > pair ) { return 0; } public double method( Pair< Double, Double > pair ) { return 1.0; } } ``` This actually compiles and works like one would expect. But if the return types are made to be the same, this doesn't compile, with the expected "name clash: method(Pair) and method(Pair) have the same erasure" Given that the return type isn't part of the method signature, how is this overloading possible?

Original source

Related problems