Ссылка неоднозначна с дженериками

У меня здесь довольно сложный случай с дженериками и перегрузкой методов. Посмотрите этот пример класса:

public class Test {
    public  void setValue(Parameter parameter, T value) {
    }

    public  void setValue(Parameter parameter, Field value) {
    }

    public void test() {
        // This works perfectly.  is bound to String
        // ambiguity between setValue(.., String) and setValue(.., Field)
        // is impossible as String and Field are incompatible
        Parameter p1 = getP1();
        Field f1 = getF1();
        setValue(p1, f1);

        // This causes issues.  is bound to Object
        // ambiguity between setValue(.., Object) and setValue(.., Field)
        // is possible as Object and Field are compatible
        Parameter p2 = getP2();
        Field f2 = getF2();
        setValue(p2, f2);
    }

    private Parameter getP1() {...}
    private Parameter getP2() {...}

    private Field getF1() {...}
    private Field getF2() {...}
}

Приведенный выше пример отлично компилируется в Eclipse (Java 1.6), но не с помощью команды Ant javac (или команды javac JDK), где я получаю такое сообщение об ошибке при втором вызове setValue :

ссылка на setValue неоднозначна, оба метода setValue (org.jooq.Parameter, T) in Тест и метод setValue (org.jooq.Parameter, org.jooq.Field) in Test match

Согласно спецификации и моему пониманию того, как работает компилятор Java, всегда следует выбирать наиболее конкретный метод: http://java.sun.com/docs/books/jls/third_edition /html/expressions.html#20448

В любом случае, даже если привязан к Object , оба метода setValue являются приемлемыми кандидатами. для вызова вариант с параметром Поле всегда кажется более конкретным. И он работает в Eclipse, но не с компилятором JDK.

UPDATE :

Таким образом, он будет работать как в Eclipse, так и с компилятором JDK (конечно, с предупреждениями о rawtypes). Я понимаю, что правила, указанные в спецификациях , довольно специфичны, когда речь идет о дженериках. Но я нахожу это довольно запутанным:

    public  void setValue(Parameter parameter, Object value) {
    }

    // Here, it's easy to see that this method is more specific
    public  void setValue(Parameter parameter, Field value) {
    }

ОБНОВЛЕНИЕ 2 :

Даже с универсальными шаблонами я могу создать обходной путь, позволяющий избежать привязки типа к Object во время вызова setValue путем добавления дополнительной однозначной косвенной адресации, называемой setValue0 . Это заставляет меня думать, что привязка T к объекту действительно является причиной всех проблем:

    public  void setValue(Parameter parameter, T value) {
    }

    public  void setValue(Parameter parameter, Field value) {
    }

    public  void setValue0(Parameter parameter, Field value) {
        // This call wasn't ambiguous in Java 7
        // It is now ambiguous in Java 8!
        setValue(parameter, value);
    }

    public void test() {
        Parameter p2 = p2();
        Field f2 = f2();
        setValue0(p2, f2);
    }

Я что-то не понимаю? Связана ли с этим известная ошибка компилятора? Или есть обходной путь / настройка компилятора, которые могут мне помочь?

Продолжение:

Для тех, кто заинтересован, я отправил отчет об ошибке как в Oracle, так и в Eclipse. Oracle приняла ошибку, Eclipse проанализировал ее и отклонил! Похоже, моя интуиция верна, и это ошибка в javac

36
задан Lukas Eder 1 June 2015 в 17:03
поделиться