Отправка ("test", 1.0d) приводит к ошибке компиляции Java 8, неоднозначному вызову метода xMethod (String, double ...) против xMethod (String, Object ...) - PullRequest
1 голос
/ 28 января 2020

Java 8 жалуется на то, что следующий вызов метода является неоднозначным:

reference to overloadedMethod is ambiguous
both method overloadedMethod(java.lang.String,double...) in XTest and 
     method overloadedMethod(java.lang.String,java.lang.Object...) in XTest match  
    @Test
    public void testUnboxing() {
        Double test = new Double(1.0);
        this.overloadedMethod("Hola" , test);
        this.overloadedMethod("Hola" , 1.01d);

    }

    private void overloadedMethod(String test, double... args){
        System.out.println("Method 1");

    }

    private void overloadedMethod(String test, Object... args){
        System.out.println("Method 2");

    }

Единственный способ, которым мне удалось скомпилировать этот код, это добавить ноль в конце списка параметров , который выводит метод 2.

this.overloadedMethod("Hola" , 1.01d, null);

В Oracle Docs нет ничего, что могло бы объяснить это поведение. Могу ли я, по своей бесконечной и непревзойденной мудрости, что-то упустить? Может ли это быть ошибкой в ​​Java 8?

1 Ответ

0 голосов
/ 28 января 2020

Тройные точки (varargs) являются решающим аспектом здесь. Без них версия Object просто побеждает. Однако, с varargs, это неоднозначно, даже если вместо этого вы «обновите» вариант Object... до Double.... ecj соглашается, что обычно означает, что они оба следуют spe c.

И так оно и есть; соответствующий раздел - это все 3 бита от JLS с 15.12.2.2 по JLS 15.12.2.4 .

В то время как существует «строгое», а затем «свободное» приложение, поэтому версия Object выигрывает без varargs, как только вы погружаетесь на третий уровень (переменная arity - это JLS-ese для 'varargs', эти тройные точки), такого разделения не существует, поэтому оба эти метода "подходят" на уровне 15.12.2.4. , И поэтому, это неоднозначно.


Хех, пока экспериментировал, я обнаружил ошибку java. Этот код:

public class Test {
    public static void main(String[] args) {
        double d = 5.0;
        test(d);
    }
    public void test(Double d) { System.out.println("D"); }
    public void test(double d) { System.out.println("d"); }

не компилируется, вызывая ошибку «ссылка на тест неоднозначна». Эта ошибка вдвойне ошибочна. Он не выделяет фактическую ошибку в этом коде (то есть, что методы тестирования являются методами экземпляра, они не могут быть вызваны из контекста stati c), и указывает на то, что этот вызов неоднозначен, а это не так; сделать методы тестирования stati c и код скомпилируется; победит вариант в нижнем регистре-d.

Как и ожидалось, ecj (компилятор eclipse) не страдает от этой ошибки и выдает правильную ошибку. Это имеет тенденцию быть лучше при следующих показателях c, чем javac.

...