Объяснение принципа получения и отдачи

83

Я прочитал книгу О'Рейли, в которой я узнал этот принцип получения результата .

  • Используйте extendsподстановочный знак, когда вы получаете значения только из структуры.
  • Используйте superподстановочный знак, когда вы помещаете только значения в структуру.
  • И не используйте подстановочный знак, когда вы оба хотите получить и поместить из / в структуру.

Исключения составляют:

  • Вы не можете поместить что-либо в тип, объявленный с extendsподстановочным знаком, кроме значения null, которое принадлежит каждому ссылочному типу.

  • Вы не можете получить что-либо из типа, объявленного с superподстановочным знаком, за исключением значения типа Object, который является супертипом каждого ссылочного типа.

Может ли кто-нибудь помочь мне глубже изучить это правило? Если возможно, расположите их иерархически.

JavaResp
источник
4
+1: Всегда приятно видеть, что кто-то ищет разъяснений по основам
Все
2
@Everyone, я так понимаю, вы имеете в виду фундамент в основном смысле, а не спинную сторону?
Rich Seller

Ответы:

167

Рассмотрим связку бананов. Это Collection<? extends Fruit>в том смысле, что это коллекция определенных видов фруктов, но вы не знаете (из этого объявления), какие фрукты это коллекция. Вы можете достать из него какой- нибудь предмет и знать, что это определенно будет фрукт, но вы не можете добавить к нему - возможно, вы пытаетесь добавить яблоко в связку бананов, что определенно будет неправильно. Вы можете добавить nullк нему, так как это будет допустимое значение для любого вида фруктов.

Теперь рассмотрим вазу с фруктами. Это в том смысле Collection<? super Banana>, что это коллекция некоторого типа «больше чем» Banana(например, Collection<Fruit>или Collection<TropicalFruit>). Вы определенно можете добавить к этому банан, но если вы достанете предмет из миски, вы не знаете, что получите - это вполне может быть не банан. Все, что вы знаете наверняка, - это то, что это будет действительная (возможно null) Objectссылка.

(В общем, для вопросов по обобщениям Java можно найти ответы на часто задаваемые вопросы по обобщениям Java, которые содержат ответы практически на все вопросы, связанные с универсальными шаблонами, которые вы, вероятно, зададите.)

Джон Скит
источник
но при получении фрукта из Коллекции <? extends Fruits> вы можете получить любой фрукт, но не банан. аналогично, кладя в него фрукт, вы можете добавить что-нибудь, что может не относиться к банановым фруктам
JavaResp
6
Java не позволит вам добавлять в a Collection<? extends Fruit>что- либо, кроме null, именно по этой причине, и вам придется явно приводить результат выборки элемента именно по этим причинам.
Джон Скит,
@JonSkeet Это может быть глупый вопрос, но в каких случаях полезно не иметь «доступа» к методам add () и get ()? Я имею в виду, чтобы получить () какой-то объект из списка, вы должны сначала добавить его, верно? И наоборот, зачем вам его добавлять, если потом вы не можете его получить?
Timmos
7
@Timmos: Просто потому, что что- то должно иметь возможность добавлять значение, не означает, что весь код должен иметь возможность. Например, для отображения списка имен людей мне может просто понадобиться Collection<? extends Person>(или, что более вероятно, просто Iterable<? extends Person>, но ...). Код, создающий эту коллекцию, может нуждаться в том, чтобы он был Collection<Employee>, а код потребления - нет.
Джон Скит
5
@Timmos: В этом случае вам нужно точно сказать , что вы имели в виду под словом «это» ... но да, правила универсальных шаблонов Java разработаны для обеспечения безопасности типов.
Джон Скит