为什么Java的类型擦除不会打破这个?

Kev*_*vin 13 java

public class Test {
    public static class Nested<T> {
        public T val;
        Nested(T val) { this.val = val; }
    }
    public static void main(String[] args) {
        Nested<Integer> a = new Nested<Integer>(5);
        Nested<Integer> b = new Nested<Integer>(2);
        Integer diff = a.val - b.val;
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码工作正常.但是,如果我向嵌套添加一个方法:

T diff(Nested<T> other) { return this.val - other.val; }
Run Code Online (Sandbox Code Playgroud)

我收到编译错误:

operator - cannot be applied to T,T
Run Code Online (Sandbox Code Playgroud)

这对我来说很有意义.T的类型在运行时被擦除,因此Java不能应用仅为某些类(如Integer)定义的运算符.但为什么a.val - b.val 工作呢?

编辑:

很多好的答案.感谢大家.如果我理解正确的话,它的要点是编译器可以向Integer中添加强制转换,a.val - b.val因为它知道a并b实例化为.但是,由于发生在泛型函数定义的主体内部(其中T仍然可以是任何东西),编译器无法添加使" "工作所必需的强制转换.这导致了一个更有趣的问题,即,如果Java编译器能够内联,那么像diff这样的泛型函数是否可以工作?Nested<Integer>this.val - other.val-

das*_*ght 9

两者之间的区别在于您是在通用方法中还是在其外部.

你得到的绝对正确的方法T是在方法中不知道是Integer,所以运算符减去-不能应用.但是,当你在main(),一般的方法外,编译器知道你实例Nested有Integer,所以它很清楚如何应用操作.尽管泛型的实现已经擦除了生成代码的类型Nested<T>,但编译器并没有考虑a并且b在以下方面Nested<T>:它具有足够的知识来插入适当的强制转换,取消结果,并应用减号-运算符.


S.D*_*.D. 8

您将收到编译时错误,而不是运行时错误.

public static void main(String[] args) {
    Nested<Integer> a = new Nested<Integer>(5);
    Nested<Integer> b = new Nested<Integer>(2);
    Integer diff = a.val - b.val;
}
Run Code Online (Sandbox Code Playgroud)

在这里,编译器知道两者T都是Integer.你刚宣布<Integer>.

T diff(Nested<T> other) { return this.val - other.val; }
Run Code Online (Sandbox Code Playgroud)

在这里,编译器不确定T.它可能是任何东西.而且,只-允许使用数字运算符.