为什么以下代码会自动装箱为错误的类型并进行编译?

Why does the following code autoboxes to wrong types and compiles?

class Test {
    public static <T> boolean test(T a, T b) {
        return a.equals(b);
    }

    public static void main(String[] args) {
        int i = 0;
        long j = 0;
        if (!test(i, j)) {
            throw new RuntimeException("i is not equal to j");
        }
    }
}

在上面的代码片段中,我预计会发生以下两种情况之一:

  1. 会出现编译错误,因为i被自动装箱为Integerj被自动装箱为Long并且声明方法 test 要求它的两个参数属于同一类型。

  2. ij 都被自动装箱为 Long 和要编译的代码,运行 显示 ij 相等。

但实际上发生的是 i 被自动装箱为 Integer 并且 j 被自动装箱为 Long 并且代码编译没有错误。这不和test的声明相矛盾吗?允许这样的代码的原因是什么?

如果 i 被装箱到 Integer 并且 j 被装箱到 Long,调用方法 test 仍然是合法的通用类型假定为 java.lang.Number,它是 IntegerLong.

的超类型

其实你可以用任何两个对象调用你的test方法,因为T可以作为基类型Object.方法上的泛型根本不限制其参数。