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

Viewed 69
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");
        }
    }
}

In the code snippet above I am expecting one of the following two things to happen:

  1. There will be a compiler error, because i is autoboxed to Integer and j is autoboxed to Long and the declaration of the method test requires that both of its arguments are of the same type.

  2. Both i and j to be autoboxed to Long and the code to compile and run showing that i and j are equal.

But what happens actually is i is autoboxed to Integer and j is autoboxed to Long and the code compiles without error. Doesn't this contradict with the declaration of test? What is the reason to allow such code?

1 Answers

If i is boxed to an Integer and j is boxed to a Long, it's still legal to call the method test with its generic type assumed to be java.lang.Number, which is a supertype of both Integer and Long.

In fact, you can call your test method with any two objects, because T can be taken as the base type Object. The generics on the method do not restrict its arguments at all.

Related