Ограниченные параметры Java в универсальных методах - PullRequest
10 голосов
/ 19 декабря 2011

Я протестировал некоторые вещи с ограниченными параметрами в общих методах и обнаружил странное поведение.
Было бы здорово, если бы кто-нибудь мог объяснить две ошибки в следующем фрагменте кода.

Представьте, что есть два класса Class1 и Class2, оба расширяются от BaseClass. Class2 реализует интерфейс.

В Class1 у меня есть метод, который возвращает экземпляр Class2 следующим образом:

public class Class2 extends BaseClass implements Interface {

    @Override
    public void method() {
        System.out.println("test"); //$NON-NLS-1$
    }
}

public class Class1 extends BaseClass {

    public <T extends BaseClass & Interface> T getTwo() {
        return new Class2();
        // Error: Type mismatch: cannot convert from Class2 to T
    }

    public static void main(String[] args) {
        Interface two = new Class1().getTwo();
        // Error: Bound mismatch: The generic method getTwo() of type Class1 is
        // not applicable for the arguments (). The inferred type Interface is
        // not a valid substitute for the bounded parameter <T extends BaseClass
        // & Interface>
        System.out.println(two);
    }
}

Ответы [ 2 ]

5 голосов
/ 19 декабря 2011

Первая ошибка компиляции возникает из-за того, что параметры типа, объявленные методами, определяются вызывающей стороной, а не реализацией метода.То есть, учитывая

class Class3 extends BaseClass implements Interface { ... }

, вызывающая сторона может написать

Class3 c3 = new Class1().<Class3>getTwo();

, но реализация метода возвращает Class2, который не является подтипом T = Class3.

Вторая ошибка компиляции возникает из-за того, что параметры типа, которые явно не указаны вызывающей стороной, выводятся из аргументов метода и типа переменной, которой назначено возвращаемое значение метода.Этот вывод не удается здесь.Обычный обходной путь, рекомендованный Спецификацией языка Java, заключается в явном указании параметров типа в таких случаях (вывод типа предназначен для удобства простых случаев; он не предназначен для охвата всех случаев).

Что касается того, как правильно объявить этот параметр типа, мне нужно знать, что вы пытаетесь выполнить с помощью этих объявлений.

4 голосов
/ 19 декабря 2011

Зачем использовать дженерики для метода getTwo, когда вы знаете , что это Class2? Просто сделайте это:

public Class2 getTwo() {
    return new Class2();
}

Если вы переопределяете метод public <T extends BaseClass & Interface> T getTwo(), компилятор позволит вам объявить ваш импл как public Class2 getTwo(), когда ваш T для вашего импл равен Class2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...