Когда использовать примитив и когда ссылочные типы в Java - PullRequest
21 голосов
/ 24 марта 2010

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

Этот вопрос вызвал у меня любопытство.

Ответы [ 10 ]

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

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

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

В одном из случаев необходимо использовать класс-оболочку, например Integer, в случае использования generics , поскольку 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 может служить справочной информацией о том, как эти методы будут вести себя в классах-оболочках для примитивов.

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

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

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

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

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

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

public Integer getValue();

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

int myValue = getValue();

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

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

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

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

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

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

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

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

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

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

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

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

List<int> list; // won't compile
List<Integer> list; // correct
1 голос
/ 24 марта 2010

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

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

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

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

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

0 голосов
/ 07 октября 2017

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

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

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

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

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

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

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

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

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

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

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