Сегодня я наткнулся на некоторый рабочий код Java, который я даже не ожидал компиляции. Уменьшенный до минимума, он выглядит следующим образом:
import java.util.List;
interface A {
<T> List<String> foo();
}
interface B {
<T> List<Integer> foo();
}
class C implements A, B {
@Override
public List<?> foo()
{
return null;
}
}
На первый взгляд параметр типа <T>
методов foo
в A
и B
выглядит ненужным, поскольку T
больше не используется. Во всяком случае, я узнал, что это играет решающую роль в разрешении конфликтующих типов возвращаемых значений сосуществовать в одной и той же реализации: если один или оба из <T>
не учитываются, код не компилируется. Здесь нерабочая версия:
import java.util.List;
interface A {
List<String> foo();
}
interface B {
List<Integer> foo();
}
class C implements A, B {
@Override
public List<?> foo()
{
return null;
}
}
Мне не нужно исправлять фрагменты кода выше, поскольку это просто примеры, которые я изложил, чтобы объяснить мою мысль. Мне любопытно понять, почему компилятор ведет себя по-другому с ними. Может кто-нибудь объяснить, какие именно правила здесь делают?