2016-04-15 6 views
-1

Я не могу объяснить, почему этот простой код не компилируется.Ошибка компиляции Java в методе с общим типом возврата

class Foo { 
    <T extends Foo> T method() { 
     return this; 
    } 
} 

Ошибка: Type mismatch: cannot convert from Foo to T.
Почему бы и нет? T определяется как Foo или его подкласс.

В соответствующей заметке эквивалентный пример Scala делает, поэтому ошибка Java не связана с ограничением JVM.

class Foo { 
    def method[T <: Foo] = this 
} 

UPDATE: Я нашел лаконичный совет в Java Tutorials о generic methods.

Общие методы позволяют использовать параметры типа для выражения зависимостей между типами одного или нескольких аргументов метода и/или его возвращаемого типа. Если такой зависимости нет, общий метод не должен использоваться.

Мое толкование заключается в том, что общий метод применим только в двух сценариях.

  1. Существует зависимость между двумя (или более) типами аргументов метода.
  2. Существует зависимость между возвращаемым типом метода и одним (или более) его типами аргументов.

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


UPDATE2: Теперь, когда я знаю об этом, я заметил пару примеров этого анти-паттерна в проектах с открытым исходным кодом.


Update3: Я думаю, что я нашел требование для общих методов, которые не включают несколько параметров или тип возвращаемого значения. Кажется, что множественное наследование является исключением из приведенного выше правила из учебных пособий Java.

<T extends Foo & Bar> void method(T foobar) { 
    // Call Foo method. 
    // Call Bar method. 
} 
+0

Ваша интерпретация видеоролика Java Tutorials зависит от того, как вы разбираете предложение. Является ли это «зависимостями между типами одного или нескольких аргументов к методу« + »и/или его возвращаемому типу» или «зависимостям между типами одного или нескольких аргументов« + »методу и/или его возвращаемому типу». В последнем случае зависимость может быть между типами одного или нескольких аргументов и самим методом. –

ответ

6

Я думаю, вы поняли, как работает Java дженериков:

<T extends Foo> T method() { 

Это означает, что абонент этого метода может выбрать то, что подтип Foo они хотят и просят. Например, вы могли бы написать

Foo foo = new Foo(); 
SubFoo subfoo = foo.<SubFoo>method(); 

... и ожидать SubFoo обратно, но ваша method реализация не может вернуть SubFoo, и это было бы потерпеть неудачу.(Я не говорю Scala, но я полагаю, это означает, что ваша реализация Scala в действительности не является «эквивалентом.»)

Если вы хотите, чтобы ваш метод, чтобы иметь возможность вернуть подтип Foo что реализации выбирает , вместо звонящего, а затем просто напишите

Foo method() { 
    return this; 
} 
+0

Спасибо. Это заставляет меня задаться вопросом, как « T method()» может быть реализован без (небезопасного) кастинга? – jaco0646

+2

Не может. Если вы просто не вернете нуль или бросок. –

+1

Или делать 'while (true);'. –

Смежные вопросы