Это - маленький отрывок кода, взятого от некоторых примеров, которые сопровождают Стэнфордский Синтаксический анализатор. Я разрабатывал в Java в течение приблизительно 4 лет, но никогда не имел очень глубокого понимания того, на что этот стиль кода, как предполагается, указывает.
List<? extends HasWord> wordList = toke.tokenize();
Я не волнуюсь по поводу деталей кода. То, чем я смущен, - то, что точно универсальное выражение, как предполагается, передает на английском языке.
Кто-то может объяснить это мне?
? extends HasWord
означает «Класс / интерфейс, расширяющий HasWord
». Другими словами, HasWord
или любой из его дочерних элементов ... в основном все, что будет работать с instanceof HasWord
плюс null
.
Говоря более техническим языком, ? extends HasWord
- это ограниченный подстановочный знак, описанный в пункте 31 Эффективное третье издание Java , начиная со страницы 139. Та же глава из 2-го издания доступна в Интернете в виде PDF ; часть ограниченных подстановочных знаков - это элемент 28, начиная со страницы 134.
Обновление: ссылка PDF была обновлена, так как Oracle некоторое время назад удалил ее. Теперь он указывает на копию, размещенную в Школе электронной инженерии и информатики Лондонского университета королевы Марии.
Обновление 2: давайте подробнее рассмотрим, почему вы хотите использовать подстановочные знаки.
Если вы объявляете метод, сигнатура которого ожидает передачи в List
, то единственное, что вы можете передать, - это List
.
Однако, если указанная подпись была Список extends HasWord>
, то вместо этого вы можете передать List
.
Обратите внимание на небольшую разницу между List расширяет HasWord>
и List super HasWord>
. Как выразился Джошуа Блох: PECS = производитель-расширяет, потребитель-супер.
Это означает, что если вы передаете коллекцию, из которой ваш метод извлекает данные (т.е. коллекция создает элементы для использования вашим методом), вы должны использовать extends
.Если вы передаете коллекцию, в которую ваш метод добавляет данные (т.е. коллекция использует элементы, созданные вашим методом), она должна использовать super
.
Это может показаться запутанным. Однако вы можете увидеть это в команде List
sort
(которая представляет собой просто ярлык для версии Collections.sort с двумя аргументами). Вместо использования Comparator
, на самом деле требуется Comparator супер T>
. В этом случае Компаратор использует элементы списка List
, чтобы изменить порядок самого списка.
На английском языке:
Это
Список
некоторого типа, расширяющий классHasWord
, в том числеHasWord
В общем случае ?
в дженериках означает любой класс. И extends SomeClass
указывает, что этот объект должен расширять SomeClass
(или быть этим классом).
Знак вопроса означает «любой тип». Только ?
означает
Любой тип, расширяющий
Объект
(включаяОбъект
)
, в то время как ваш пример выше означает
Любой тип, расширяющий или реализующий
HasWord
(включаяHasWord
, еслиHasWord
- неабстрактный класс)
List extends HasWord>
принимает любые конкретные классы, которые расширяют HasWord. Если у вас есть следующие классы...
public class A extends HasWord { .. }
public class B extends HasWord { .. }
public class C { .. }
public class D extends SomeOtherWord { .. }
... wordList
может содержать ТОЛЬКО список либо As, либо Bs, либо смесь обоих, потому что оба класса расширяют одного родителя, либо null
(который не проходит проверку на instanceof для HasWorld
).
Возможно, поможет надуманный пример из «реального мира».
У меня на работе есть мусорные баки разного вкуса. Все урны содержат мусор, но некоторые урны являются специализированными и не вмещают все виды мусора.Итак, у нас есть Bin
и Bin
. Система типов должна гарантировать, что я не могу поместить свой HalfEatenSandwichRubbish
ни в один из этих типов, но он может попасть в общую корзину Bin
. Если бы я хотел поговорить о корзине
из мусора
, которая может быть специализированной, поэтому я не могу складывать несовместимый мусор, то это будет корзина расширяет мусор>
.
(Примечание: ? Extends
не означает доступ только для чтения. Например, я могу с надлежащими мерами предосторожности вынуть мусор из корзины неизвестного назначения, а затем положить его обратно в другое место. .)
Не уверен, насколько это помогает. Указатель на указатель при наличии полиморфизма не совсем очевиден.