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

问题描述

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自动装箱到Integer,而j自动装箱到Long,并且方法{{1的声明}}要求其两个参数都属于同一类型。

  2. testi都将自动装箱为Long,并且要编译并运行的代码显示ji相等。

但是实际上发生的是将j自动装箱到i,将Integer自动装箱到j,并且代码编译没有错误。这与Long的声明不矛盾吗?允许使用此类代码的原因是什么?

解决方法

如果i被装在Integer上,而j被装在Long上,则以其通用类型调用方法test仍然合法假定为java.lang.Number,它是IntegerLong的超类型。

实际上,您可以使用 any 两个对象来调用test方法,因为T可以作为基本类型Object。该方法上的泛型根本不限制其参数。