Java中的类型擦除和重载:为什么这样做?

Kyl*_*wey 18 java overloading type-erasure

我有以下代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这实际上编译和工作就像人们期望的那样.但是如果返回类型相同,则不会编译,预期的"名称冲突:方法(对)和方法(对)具有相同的擦除"

鉴于返回类型不是方法签名的一部分,这种重载怎么可能?

irr*_*ble 9

考虑以下4种方法

           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
Run Code Online (Sandbox Code Playgroud)

根据当前的Java语言规范,

  • m1和m2不能共存,m3和m4也不能共存.因为它们具有相同的参数类型.

  • m1和m3可以共存,m1和m4也可以共存.因为它们有不同的参数类型.

但是javac 6只允许m1 + m4,而不是m1 + m3.这与方法的字节码表示有关,包括返回类型.因此,m1 + m4可以,但不是m1 + m3.

这是Java和JVM规范看不到的混乱.javac没有"正确"的方式.

虽然很糟糕,但好消息是,重载是一种虚荣,而不是必需品.我们总是可以为这些方法使用不同的,更具描述性和不同的名称.


SLa*_*aks 6

重载在编译时完成.

尽管通用参数在运行时被擦除,但编译器仍可使用它们来解决重载问题.