Когда использовать примитив и когда ссылочные типы в Java

в этом случае вы должны использовать примитивные типы(int) и ссылочные типы (Integer)?

этой вопрос разожгло мое любопытство.

10 ответов


в этом случае вы должны использовать примитивные типы(int) или ссылочные типы (Integer)?

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

в одном из случаев необходимо использовать класс-оболочку, такой как Integer в случае использования дженериков, поскольку Java не поддерживает использование примитивных типов в качестве типа параметры:

List<int> intList = new ArrayList<int>();               // Not allowed.
List<Integer> integerList = new ArrayList<Integer>();   // Allowed.

и, во многих случаях, я воспользуюсь автоупаковка и распаковывание, поэтому мне не нужно явно выполнять преобразования из примитивов в свой класс-оболочку и наоборот:

// Autoboxing will turn "1", "2", "3" into Integers from ints.
List<Integer> numbers = Arrays.asList(1, 2, 3); 

int sum = 0;

// Integers from the "numbers" List is unboxed into ints.
for (int number : numbers) {
  sum += number;
}

кроме того, в качестве дополнительного Примечания при преобразовании из примитивов в объекты класса-оболочки, а уникальные экземпляры объектов не нужны, используйте valueOf метод, предоставляемый методом wrapper, поскольку он выполняет кэширование и возвращает тот же экземпляр для определенного значения, уменьшая количество объектов, которые создаются:

Integer i1 = Integer.valueOf(1);   // Prefer this.
Integer i2 = new Integer(1);       // Avoid if not necessary.

подробнее о valueOf методы, спецификация API для Integer.valueOf метод может служить ссылкой на то, как эти методы будут вести себя в классах-оболочках для примитивов.


Это действительно зависит от контекста. Сначала предпочитайте примитивный, потому что он более интуитивный и имеет меньше накладных расходов. Если это невозможно по причинам generics / autoboxing или если вы хотите, чтобы он был nullable, перейдите к типу оболочки (сложный тип, как вы его называете).


общие правила, которым я следую при создании API, можно резюмировать следующим образом:

  1. если метод должны верните значение, используйте примитивный тип
  2. если метод не всегда может применяться (например: getRadioId(...) на объекте, где такой идентификатор может не существовать), затем верните целое число и укажите в JavaDocs, что метод вернет null в некоторых случаях.

на #2, Обратите внимание на НПС, когда автоупаковка. Если у вас есть метод определяется как:

public Integer getValue();

а затем назовите его следующим образом:

int myValue = getValue();

в случае, когда getValue() возвращает null, вы получите NPE без очевидной причины.


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

List<Integer> intList = new ArrayList<Integer>();

int n = Integer.parseInt("123");

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

Autoboxing искушает нас верить int и Integer (например) взаимозаменяемы, но это ловушка. Если вы смешиваете два вида значений без разбора, вы можете сравнить два целых значения с == или пытается открыв null не осознавая этого. В результате ошибки могут быть прерывистыми и трудно отследить.

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

при работе со строками, мы можем просто сказать n00bs никогда сравните их с ==, как мы делали все вместе. Но сравнение примитивов с == вполне допустимо; хитрость (спасибо автоупаковка) является будучи уверенным, что значения действительно являются примитивами. Компилятор теперь позволит нам объявить переменную как Integer и используйте его, как если бы это было int; это означает, что мы должны проявлять высокий уровень дисциплины и рассматривать его как ошибку, когда кто-то делает это без уважительных причин.


поскольку Java делает что-то под названием авто-бокс и авто-распаковка, вы должны использовать примитивный тип int в большинстве случаев из-за меньшей нагрузки.

единственный раз, когда вам абсолютно необходимо использовать Integer, - это дженерики.

List<int> list; // won't compile
List<Integer> list; // correct

вместо того, чтобы называть их "сложными типами", вам лучше всего думать целочисленными, двойными и т. д. как "классы", так и int, double и т. д. как "примитивы".

Если вы делаете любой тип сложной математики, числовое представление на основе классов, такое как Integer и Double, будет громоздким и замедлит вас - многие математические операции могут быть выполнены только с примитивами.

с другой стороны, если вы пытаетесь поставить свои номера в коллекции, такие как списки и карты, те коллекции могут содержать только объекты-и поэтому вы должны использовать (или конвертировать в) классы типа Integer и Double.

лично я использую примитивы, когда мне это удается, и только конвертирую в представления класса, такие как Integer, когда пришло время делать ввод или вывод, и транспорт требует этих представлений.

однако, если вы вообще не занимаетесь математикой, а вместо этого просто передаете значения прямо через свой код, вы можете сэкономить проблема, связанная исключительно с формами на основе классов (например, Integer).


Я не думаю, что есть какое-то правило как таковое. Я бы выбрал типы над примитивами (Integer над int), когда я пишу сигнатуры методов, карты, коллекции, объекты данных, которые передаются. Таким образом, я все равно хотел бы использовать Integer вместо int даже внутри методов и т. д. Но если вы считаете, что это слишком много проблем (для ввода дополнительного "eger"), то можно использовать ints для локальных переменных.


Если вы хотите установить атрибут для сеанса, вы должны использовать объект типа Integer, Boolean, String в сервлетах. Если вы хотите использовать value, вы можете использовать примитивные типы. Объекты могут быть null, но не примитивы. И если вы хотите сравнить типы для примитивов, используйте == но объекты используют .равно, потому что в object comparision == looks not values он выглядит, если это те же объекты. И использование примитивов делает код быстрее.


один случай, в котором Integer может быть предпочтительнее, когда вы работаете с базой данных, где числовые записи могут быть нулевыми, так как вы не сможете представить нулевое значение с int.

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


Я думаю, что это немного поздно, но я хотел бы добавить мое мнение на всякий случай.

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

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