В чем разница между? и T в подписи класса и метода?
почему
public interface ArrayOfONEITEMInterface <T extends ONEITEMInterface>{
public List<T> getONEITEM();
}
скомпилировать, но не
public interface ArrayOfONEITEMInterface <? extends ONEITEMInterface>{
public List<?> getONEITEM();
}
В чем разница? и T в подписи класса и метода?
Ответы
Ответ 1
?
является подстановочным знаком и означает любой подкласс ONEITEMInterface
, включающий в себя.
T
- это конкретная реализация ONEITEMInterface
в этом случае.
Так как ?
является подстановочным знаком, между вашим ?
в объявлении класса и ?
в объявлении метода нет никакой связи, поэтому он не будет компилироваться. Просто List<?> getONEITEM();
будет компилироваться.
первый сценарий означает, что весь класс может обрабатывать ровно один тип Bar
для каждого экземпляра.
interface Foo<T extends Bar> {
List<T> get();
}
второй сценарий позволяет каждому экземпляру работать с любым подтипом Bar
interface Foo {
List<? extends Bar> get()
}
Ответ 2
Предложение <T extends ONEITEMInterface>
объявляет параметр типа с именем T
. Это позволяет вашему типовому типу ArrayOfONEITEMInterface
ссылаться на параметр в другом месте. Например, вы можете объявить метод типа void add(T t)
.
Не называя параметр типа, как бы вы на него ссылались? Если вы никогда не ссылаетесь на параметр типа, почему ваш тип является общим в первую очередь? Например, вам не нужен параметризованный тип, чтобы сделать что-то вроде этого:
public interface ArrayOfONEITEMInterface {
List<? extends ONEITEMInterface> getONEITEM();
}
Не имеет смысла объявлять анонимный параметр типа, поэтому он является синтаксически незаконным.
Ответ 3
T является заполнителем для типа, который будет предоставляться классом реализации или экземпляра.
? является заполнителем, говорящим: "Я не знаю и не забочусь о том, что такое общий тип" обычно используется, когда работа, которую вы будете делать на объекте-контейнере, не должна знать тип.
Причина, по которой вы не можете использовать '?' в определении класса/интерфейса, потому что там указано значение, определяющее имя заполнителя (и тип будет предоставлен в другом месте). Ввод "?" не имеет смысла.
Кроме того, заполнитель не должен быть T, он может любой стандартной переменной Java. По соглашению, это один главный символ, но не обязательно.
Ответ 4
? позволяет вам иметь список Неизвестных типов, где, когда T требует определенного типа.