Overload function int… and long… simultaneously

2019-05-22 12:07发布

I want to create two functions, say

long min(long...);
int min(int...);

But when I try to invoke the second i.e min(1, 5) one I get ambiguous method call

Is there workaround except renaming?

4条回答
地球回转人心会变
2楼-- · 2019-05-22 12:50

The problem is when you invoke those method with an integer, none of the methods provide exact match for the argument, as you used var-args. Also, both the var-args can take int values separated by commas as argument. Hence the ambiguous method error.

When you call overloaded method, Compiler chooses the exact match first. Then the nearest type to cast.

Now, since var-args is just an array, compiler cannot decide which array to use while passing an integer value. As, neither arrays can be considered as exact match or nearest conversion. So, it takes both the method eligible for call.

There are lot more rules regarding the method invocation in case of Overloading. You can learn those from the Java Language Specification.


As in @assylias answer this problem has been fixed in Java 7. But it will not work in Java version < 7.

查看更多
ら.Afraid
3楼-- · 2019-05-22 12:57

It is a known bug

The behaviour you describe is a bug which has been fixed with Java 7. See details in the release notes, section called "Changes in Most Specific Varargs Method Selection".

The reason why it should compile

Variable arity comes last in determining the most specific method. The rules to determine which vararg method applies when there are several are defined in JLS 15.12.2.4 - here is an extract:

One variable arity member method named m is more specific than another variable arity member method of the same name if either:
- [...]
- One member method has k parameters and the other has n parameters, where n ≥ k, and:

  • The types of the parameters of the first method are U1, ..., Uk-1, Uk[].
  • The types of the parameters of the other method are T1, ..., Tn-1, Tn[].
  • For all j from 1 to n, Uj <: Tj

In your case, k = n, and U1[] = int[] and T1[] = long[] so the determination can be made if int <: long or the opposite.

In other words, the type taken into account is not int[] vs. long[] but int vs long. And it happens that int <: long so the int... method should be chosen and it should compile.

Conclusion:

The code should (and does) compile fine with Java 7 but would not compile with Java 5 or 6. The code below prints int with Java 7:

public class Test1 {
    public static void main(String[] args) {
        new Test1().m(1, 2);
    }
    int m(int... i) {
        System.out.println("int");
        return 0;
    }
    long m(long... i) {
        System.out.println("long");
        return 0;
    }
}
查看更多
够拽才男人
4楼-- · 2019-05-22 13:01

Those method signatures are unique, and are valid method overloads.

The problem must be in the method call argument. My guess is that you are calling the method with a literal, like:

min(100) 

And it doesnt like that because 100 is an integer literal, but it gets automatically converted to a long.

disambiguating the method calls by using L at the end of long literals should fix the problem:

min(100L)

Also, you could make the calls explicit by using the Java Object Integer and Long, and let autoboxing take care of the conversion to primitive types:

min(new Long(100))
min(new Integer(100))
查看更多
疯言疯语
5楼-- · 2019-05-22 13:03

Try this

public class Test {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new Test().m(100L,512L);
        new Test().m(100,512);
    }

    int m(int... i) {
        System.out.println("int");
        return 0;
    }

    long m(long... i) {
        System.out.println("long");
        return 0;
    }
}
查看更多
登录 后发表回答