Добавление значений в List<? extends Number> в Java

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Java
Скопировать код
List<Number> numbers = new ArrayList<>();
numbers.add(42);  // Integer, отсылка к главному вопросу жизни, Вселенной и всего остального...
numbers.add(3.14);  // Double, ведь число Пи любит каждый, не так ли?
List<? extends Number> readOnlyNumbers = numbers;

Для начала создайте List<Number>, позволяющий добавлять числа, а затем приведите его к List<? extends Number>, чтобы ограничиться операциями только для чтения. Этот подход обеспечивает полиморфизм и гарантирует, что список может содержать любые подтипы Number, при это обеспечивая типовую безопасность.

Кинга Идем в IT: пошаговый план для смены профессии

Особенности подстановочных символов и обход ограничений

Неизменяемость List<? extends Number>

Список List<? extends Number> запрещает добавление элементов, поскольку во время выполнения Java не может определить, какой именно подтип должен быть использован. Необходимо учитывать этот факт в работе со списком.

Стратегии добавления в список

Рассмотрите использование List<Number> или List<? super Number>, которые предоставляют большую гибкость для добавления объектов класса Number или его подклассов, сохраняя при этом преимущества использования обобщенных типов.

Копирование элементов с помощью Collections.copy()

Метод Collections.copy() отлично подходит для работы с подстановочными символами и позволяет копировать элементы из совместимых списков, устраняя ограничения использования обобщений.

Работа с ключевым словом super

Гибкость при добавлении элементов

Использование List<? super Number> предоставляет возможность добавлять любые подклассы Number, делая его идеальным для записи, но оно не ограничено определенным подтипом.

Java
Скопировать код
List<Object> objects = new ArrayList<>();
List<? super Number> superNumbers = objects;
superNumbers.add(42);        // Integer, в данном контексте – настоящий супергерой
superNumbers.add(3.1415f);   // Float, поскольку точность важна

Ограничения при работе с super

Использование List<? super T> прекрасно подходит для записи значений, однако может вызвать сложности при чтении, поскольку все значения будут рассматриваться как объекты класса Object. Здесь стоит найти баланс между гибкостью и удобством использования.

Визуализация

Представьте, что List<? extends Number> – это набор ячеек для определенных форм. Каждая ячейка принимает только объекты своей формы:

Markdown
Скопировать код
     🔲
   /🔼🔽\
____|____
|         |
|  🟡🟥🟦  |
|_________|

Например:

  • 🟥 (Float)
  • 🟦 (Double)
Markdown
Скопировать код
Вы можете спустить блок (число) **вниз** в подходящую ячейку...
       _______
     🔲|___🟦___|             
     /🔼🔽\     
  {...} // <- Здесь список принимает только объекты Double.

... Однако ни одна другая форма не подойдет, как упрямый осел.

Таким образом, List<? extends Number> – это эгоистичная структура, которая может "смахнуть" вас в сторону, если вы попытаетесь добавить в нее несоответствующий подтип!

Как избежать распространенных проблем

Безопасность операций

Избегайте небезопасных преобразований типов или методов, обходящих проверки типов. Это часто приводит к ошибкам во время выполнения. Помните, что типовая безопасность – это одна из ключевых особенностей Java.

Точность объявления

Выберите List<Number>, если вы планируете управлять содержимым списка. Это поможет избежать ошибок типа capture#1-of ? extends Number и обеспечит возможность чтения и записи.

Осторожность при инициализации

Вы можете задать значения для List<? extends Number> в момент его инициализации. После этого список станет неизменяемым, что гарантирует сохранение его типовой чистоты.

Полезные материалы

  1. Дженерики с подстановочными символами (The Java™ Tutorials > Бонус > Дженерики) — официальное руководство Oracle по использованию подстановочных символов в дженериках.
  2. Урок: Дженерики (Обновлено) (The Java™ Tutorials > Изучение языка Java) – полный гайд по дженерикам в Java от Oracle.
  3. java – Что такое PECS (Producer Extends Consumer Super)? – Stack Overflow – дискуссия о применении PECS в дженериках в сообществе разработчиков.
  4. AngelikaLanger.com – ЧаВо о Дженериках Java – Часто Задаваемые Вопросы – Тренинги/Консультации Ангелики Лангер — подробный FAQ о дженериках Java от Ангелики Лангер.
  5. [Effective Java, 3rd Edition [Book]](https://www.oreilly.com/library/view/effective-java-3rd/9780134686097/) — авторитетное издание о лучших практиках в Java, включая дженерики.
  6. Подстановочные символы в Java – GeeksforGeeks — обучающая статья, объясняющая подстановочные символы в дженериках Java.