5

The overloaded functions compute1(), compute2(), and compute5() cause compilation errors if you try to use them below:

package com.example.test.reflect;

class JLS15Test2
{
    int compute1(Object o1, Integer i, Integer j)         { return 1; }
    int compute1(String s1, Integer i, int j)             { return 2; }

    int compute2(Object o1, Integer i, int j)             { return 3; }
    int compute2(String s1, Integer i, Integer j)         { return 4; }

    int compute3(Object o1, Integer i, int j)             { return 5; }
    int compute3(String s1, Integer i, int j)             { return 6; }

    int compute4(Object o1, Integer i, Integer j)         { return 7; }
    int compute4(String s1, Integer i, Integer j)         { return 8; }

    int compute5(Object o1, Integer i, Object j)          { return 9; }
    int compute5(String s1, Integer i, int j)             { return 10; }


    public static void main(String[] args) 
    {
        JLS15Test2 y = new JLS15Test2();

        // won't compile:
        // The method compute1(Object, Integer, Integer) is ambiguous 
        // for the type JLS15Test2
        // System.out.println(y.compute1("hi", 1, 1));

        // Neither will this (same reason)
        // System.out.println(y.compute2("hi", 1, 1));
        System.out.println(y.compute3("hi", 1, 1));
        System.out.println(y.compute4("hi", 1, 1));

        // neither will this (same reason)
        // System.out.println(y.compute5("hi", 1, 1));
    }
}

After reading the JLS section 15.12, I think I understand... in phase 2 (boxing/unboxing allowed, no varargs) of matching overloaded methods, when determining the "most specific method", the JLS says (in effect) that the most specific method is the one whose formal parameters are subtypes of other applicable methods, and primitives and Objects (e.g. int and Integer) are never subtypes of each other. So Integer is a subtype of Integer, and int is a subtype of int, but Integer and int are incompatible w/r/t subtype comparisons, so neither of the compute1()/compute2() pairs have a most specific method.

(Whereas in compute3() and compute4() the method with the String argument is more specific than the method with the Object argument, so the program prints 6 and 8.)

Is my reasoning correct?

Jason S
  • 171,795
  • 155
  • 551
  • 900

2 Answers2

0

Yes, your reasoning is correct.

Steven Fines
  • 450
  • 5
  • 14
0

If you add another method that just takes a primitive int and a boxed Integer, it is able to resolve which one is the proper method to called:

int compute6(int i) { return 11;}
int compute6(Integer i){return 12;}
...
System.out.println(y.compute6(1));

Based on that, I'd imagine that it has something to do with the interaction between the different parameters, and not just the separate type relationships.

James Kingsbery
  • 6,839
  • 2
  • 37
  • 65
  • 2
    No, in your example, compute6(int) matches first because the JLS specifies that methods should be located first without trying to use automatic boxing/unboxing, which is a different issue. (And yes, this is confusing. In the end, there's no easy intuitive way to manage edge cases; you just have to go by the JLS as the definitive answer.) – Jason S May 19 '11 at 17:22
  • Ah, interesting. Didn't know that. – James Kingsbery May 20 '11 at 19:41