Почему <T extends Enum <T> и SomeInterface> компилируется, но не <T extends SomeInterface & Enum <T>>?
Я не могу понять, почему метод2 не компилируется, тогда как метод1 компилируется.
Я использую Eclipse с JavaSE 1.7, и я получил следующую ошибку в методе2:
Несколько маркеров в этой строке
-
Тип Enum <T> не является интерфейсом; он не может быть указан как ограниченный параметр
-
Связанное несоответствие: тип T не является допустимым заменителем ограниченного параметра < E расширяет Enum < E → типа Enum <E>
public class Test {
public interface SomeInterface {
}
public static <T extends Enum<T> & SomeInterface> T method1() {
return null;
}
public static <T extends SomeInterface & Enum<T>> T method2() {
return null;
}
}
Ответы
Ответ 1
Если вы посмотрите на синтаксис для ограничений параметров типа в JLS 8.1.2, вы увидите:
TypeBound:
extends TypeVariable
extends ClassOrInterfaceType {AdditionalBound}
AdditionalBound:
& InterfaceType
Другими словами, только указанный первый тип может быть классом - все остальные должны быть интерфейсами.
Помимо всего прочего, это предотвращает указание нескольких классов.
Это также отражает то, как при объявлении класса вам нужно сначала поставить класс, который он расширяет, а затем интерфейсы, которые он реализует, а не наоборот.
Ответ 2
В соответствии с docs:
Переменная типа с несколькими ограничениями является подтипом всех типов, перечисленных в оценке. Если одна из границ является классом, она должна быть указана первыми. Например:
Class A { /* ... */ }
interface B { /* ... */ }
interface C { /* ... */ }
class D <T extends A & B & C> { /* ... */ }
Если привязка A сначала не указана, вы получаете ошибку времени компиляции:
class D <T extends B & A & C> { /* ... */ } // compile-time error
Так как в вашем примере method2
сначала имеет интерфейс SomeInterface
, он показывает ошибку компилятора