Пояснення принципу get-put


84

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

  • Використовуйте extendsпідстановочні , коли ви тільки отримуєте значення зі структури.
  • Використовуйте superпідстановочний знак, коли ви вкладаєте значення лише в структуру.
  • І не використовуйте підстановочний знак, коли ви обидва хочете отримати та перенести з / у структуру.

Винятки становлять:

  • Ви не можете помістити нічого у тип, оголошений із extendsпідстановкою, за винятком значення null, яке належить кожному типу посилання.

  • Ви не можете отримати нічого з типу, оголошеного superпідстановкою, за винятком значення типу Object, яке є супер типом кожного посилального типу.

Хтось може допомогти мені глибше дослідити це правило? Якщо можливо, вкажіть їх ієрархічно.


4
+1: Завжди приємно бачити, як хтось шукає роз’яснень щодо фундаменту
всі

2
@ Усі, я вважаю, ви маєте на увазі фундаментальний підставу в основному сенсі, а не на спинній стороні?
Багатий продавець

Відповіді:


168

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

А тепер розглянемо фруктову миску. Це a Collection<? super Banana>, оскільки це колекція якогось типу "більше" Banana(наприклад, Collection<Fruit>або Collection<TropicalFruit>). Ви можете однозначно додати до цього банан, але якщо ви дістаєте предмет з миски, ви не знаєте, що отримаєте - це цілком може бути не банан. Все, що ви точно знаєте, це те, що це буде дійсне (можливо null) Objectпосилання.

(Загалом, для загальних питань про Java, поширені запитання щодо Java Generics - це чудовий ресурс, який містить відповідь майже на все, що стосується дженериків, на які ви, мабуть, кинетесь.)


але, беручи фрукт з колекції <? extends Fruits>, ви можете отримати будь-який фрукт, не банан. так само, підкладаючи до нього фрукт, ви можете додати будь-яку річ, яка може не належати до бананових фруктів
JavaResp

6
Java буде заважати вам додавати щось інше, крім null, до a Collection<? extends Fruit>саме з цієї причини, і вам доведеться явно привести результат отримання елемента саме з цих причин.
Джон Скіт,

@JonSkeet Це може бути дурним питанням, але в яких випадках корисно не мати "доступу" як до методів add (), так і get ()? Я маю на увазі, щоб отримати () якийсь об’єкт зі списку, його потрібно додати спочатку, чи не так? І, наоборот, чому б ви додали його, якщо потім не зможете отримати?
Тіммос,

7
@Timmos: Те, що щось повинно додати значення, не означає, що весь код повинен мати можливість. Наприклад, для того, щоб відобразити список імен людей, мені може знадобитися просто Collection<? extends Person>(або, швидше за все, просто а Iterable<? extends Person>, але ...). Коду, що створює цю колекцію, може знадобитися Collection<Employee>, але це споживає код.
Джон Скіт,

5
@Timmos: Вам би довелося сказати саме те , що ви мали на увазі під цим "it" ... але так, правила загальних програм Java розроблені для забезпечення безпеки типу.
Джон Скіт,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.