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

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

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

24
задан Community 23 May 2017 в 12:09
поделиться

9 ответов

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

Как правило thumb, я буду использовать примитив (например, 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 , предоставляемый методом-оболочкой, поскольку он выполняет кэширование и возвращает тот же экземпляр для определенное значение, уменьшающее количество создаваемых объектов:

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

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

26
ответ дан 28 November 2019 в 23:31
поделиться

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

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

List<int> list; // won't compile
List<Integer> list; // correct
2
ответ дан 28 November 2019 в 23:31
поделиться

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

0
ответ дан 28 November 2019 в 23:31
поделиться

Если вы хотите установить атрибут для сеанса, вы должны использовать в сервлетах такие объекты, как Integer, Boolean, String. Если вы хотите использовать значение, вы можете использовать примитивные типы. Объекты могут быть нулевыми, но примитивы - нет. И если вы хотите сравнить типы для примитивов, используйте ==, но объекты используют .equals, потому что при сравнении объектов == выглядит не значениями, он выглядит, если это одни и те же объекты. А использование примитивов ускоряет код.

0
ответ дан 28 November 2019 в 23:31
поделиться

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

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

0
ответ дан 28 November 2019 в 23:31
поделиться

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

9
ответ дан 28 November 2019 в 23:31
поделиться

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

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

В пункте 2 обратите внимание на NPE при автобоксировании. Если у вас есть метод, определенный как:

public Integer getValue();

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

int myValue = getValue();

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

3
ответ дан 28 November 2019 в 23:31
поделиться

Вместо того, чтобы называть их «сложными типами», вам лучше думать о Integer, Double и т. Д. Как о «Classes», а int, double, и т.д. как «примитивы».

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

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

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

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

1
ответ дан 28 November 2019 в 23:31
поделиться

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

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

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

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

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

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

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

2
ответ дан 28 November 2019 в 23:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: