Почему коллекции Java не могут напрямую хранить типы примитивов? - PullRequest
110 голосов
/ 24 марта 2010

Java-коллекции хранят только объекты, а не примитивные типы однако мы можем хранить классы-обертки.

Почему это ограничение?

Ответы [ 7 ]

85 голосов
/ 24 марта 2010

Это было дизайнерское решение Java, и некоторые считают это ошибкой. Контейнеры хотят, чтобы объекты и примитивы не были производными от объекта.

Это то место, которое разработчики .NET извлекли уроки из JVM и реализовали типы значений и обобщения, так что во многих случаях бокс исключается. В CLR универсальные контейнеры могут хранить типы значений как часть базовой структуры контейнера.

Java решила добавить в компилятор общую поддержку на 100% без поддержки JVM. JVM, будучи тем, чем она является, не поддерживает «необъектный» объект. Обобщения Java позволяют вам притвориться, что обертки нет, но вы все равно платите за производительность бокса. Это ВАЖНО для определенных классов программ.

Бокс - это технический компромисс, и я чувствую, что детали реализации просочились в язык. Автобокс является хорошим синтаксическим сахаром, но все же снижает производительность. Во всяком случае, я бы хотел, чтобы компилятор предупредил меня, когда он будет автоматически. (Насколько я знаю, возможно, сейчас я написал этот ответ в 2010 году.)

Хорошее объяснение SO о боксе: Зачем некоторым языкам нужен бокс и распаковка?

И критика обобщений Java: Почему некоторые утверждают, что реализация обобщений Java плохая?

В защиту Java легко оглянуться назад и критиковать. JVM выдержала испытание временем и во многих отношениях является хорошим дизайном.

15 голосов
/ 24 марта 2010

Упрощает реализацию. Поскольку примитивы Java не считаются объектами, вам необходимо создать отдельный класс коллекции для каждого из этих примитивов (нет кода шаблона для совместного использования).

Конечно, вы можете сделать это, просто посмотрите GNU Trove , Примитивы Apache Commons или HPPC .

Если у вас нет действительно больших коллекций, накладные расходы на обертки не будут иметь большого значения для людей (и если у вас действительно большие примитивные коллекции, вы можете потратить усилия на изучение / построение специализированных данных структура для них).

11 голосов
/ 24 марта 2010

Это комбинация двух фактов:

  • Примитивные типы Java не являются ссылочными типами (например, int не является Object)
  • Java создает обобщенные типы, используя стирание типов ссылочных типов (например, List<?> действительно List<Object> во время выполнения)

Поскольку оба они истинны, универсальные коллекции Java не могут напрямую хранить примитивные типы. Для удобства введен автобокс, чтобы позволить примитивным типам автоматически упаковываться как ссылочные типы. Не заблуждайтесь об этом, хотя коллекции по-прежнему хранят ссылки на объекты независимо от этого.

Можно ли этого избежать? Возможно.

  • Если int - это Object, то типы ящиков вообще не нужны.
  • Если обобщения не выполняются с использованием стирания типов, то примитивы могли бы использоваться для параметров типа.
7 голосов
/ 24 марта 2010

Существует понятие автобокс и автоматическая распаковка. Если вы попытаетесь сохранить int в List<Integer>, компилятор Java автоматически преобразует его в Integer.

3 голосов
/ 24 марта 2010

Не правда ли, это ограничение?

Подумайте, хотите ли вы создать коллекцию, в которой хранятся примитивные значения. Как бы вы написали коллекцию, которая может хранить либо int, либо float, либо char? Скорее всего, у вас будет несколько коллекций, поэтому вам понадобится интлист, чарлист и т. Д.

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

0 голосов
/ 05 июля 2018

Основная причина - стратегия разработки Java. ++ 1) коллекции требуют объектов для манипуляции, а примитивы не являются производными от объекта так что это может быть другой причиной. 2) Примитивные типы данных Java не являются ссылочными типами для ex. int не является объектом.

Преодолеть: -

у нас есть концепция авто-бокса и авто-распаковки. поэтому, если вы пытаетесь сохранить примитивные типы данных, компилятор автоматически преобразует их в объект этого примитивного класса данных.

0 голосов
/ 21 февраля 2017

Я думаю, что мы можем увидеть прогресс в этом пространстве в JDK, возможно, в Java 10 на основе этого JEP - http://openjdk.java.net/jeps/218.

Если вы хотите избежать боксерских примитивов в коллекциях сегодня, есть несколько сторонних альтернатив. В дополнение к ранее упомянутым сторонним опциям есть также Коллекции Eclipse , FastUtil и Koloboke .

Сравнение примитивных карт также было опубликовано некоторое время назад под заголовком: Большой обзор HashMap: JDK, FastUtil, Goldman Sachs, HPPC, Koloboke, Trove . Библиотека GS Collections (Goldman Sachs) была перенесена в Eclipse Foundation и теперь является Eclipse Collections.

...