В каком случае вы должны использовать примитивные типы (int
) или ссылочные типы (Integer
)?
Этот question вызвал мое любопытство.
В каком случае вы должны использовать примитивные типы (int
) или ссылочные типы (Integer
)?
Этот question вызвал мое любопытство.
В этом случае вы должны использовать примитив типы (
int
) или ссылочные типы (Integer
)?
Как правило, я буду использовать примитив (например, int
), если мне не придется использовать класс, который обертывает примитив.
В одном из случаев следует использовать класс-оболочку, такой как Integer
, в случае использования generics, поскольку Java не поддерживает использование примитивных типов в качестве параметров типа:
List<int> intList = new ArrayList<int>(); // Not allowed.
List<Integer> integerList = new ArrayList<Integer>(); // Allowed.
И во многих случаях я воспользуюсь autoboxing and unboxing, поэтому мне не нужно явно выполнять преобразования из примитивов в его класс оболочки и наоборот:
// 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
может служить ссылкой на то, как эти методы будет вести себя в классах-оболочках для примитивов.
Это действительно зависит от контекста. Сначала предпочитаю примитив, потому что он более интуитивно понятен и имеет меньше накладных расходов. Если это невозможно для причин генерации/автобоксинга или если вы хотите, чтобы он был нулевым, перейдите для типа оболочки (сложный тип, как вы его называете).
Так как Java делает что-то, называемое auto-boxing и auto-unboxing, вы должны использовать примитивный тип int
в большинстве случаев из-за меньше накладных расходов.
Единственный раз, когда вам абсолютно необходимо использовать Integer, - это дженерики.
List<int> list; // won't compile
List<Integer> list; // correct
Общие правила, которые я придерживаюсь при создании API, можно суммировать следующим образом:
На # 2, обратите внимание на NPE при автобоксинге. Если у вас есть метод, определяемый как:
public Integer getValue();
И затем назовите его следующим образом:
int myValue = getValue();
В случае, когда getValue() возвращает значение null, вы получите NPE без очевидной причины.
Мое правило: используйте примитивы в штучной упаковке только тогда, когда необходимо, чтобы код был скомпилирован. Единственными местами в вашем коде, где должны отображаться имена классов примитивных оболочек, являются параметры общего типа и вызовы статических методов:
List<Integer> intList = new ArrayList<Integer>();
int n = Integer.parseInt("123");
Это совет, который я дам новым программистам на Java. По мере того как они узнают больше, они столкнутся с ситуациями, когда они должны быть более проницательными, например, при работе с Картами или базами данных, но к тому времени они также должны лучше понимать разницу между примитивами и примитивами в штучной упаковке.
Autoboxing искушает нас полагать, что int
и Integer
(например) взаимозаменяемы, но это ловушка. Если вы смешиваете два значения без разбора, вы можете в итоге сравнить два значения Integer с ==
или попытаться распаковать a null
, не осознавая этого. Получающиеся ошибки могут быть прерывистыми и сложными для отслеживания.
Это не помогает, когда сравнение примитивов в штучной упаковке с ==
иногда работает так, как если бы оно выполняло сравнение значений. Это иллюзия, вызванная тем, что значения в определенном диапазоне автоматически кэшируются в процессе автобоксинга. Это та же проблема, с которой мы всегда сталкивались со значениями String: сравнение их с ==
иногда "работает", потому что вы фактически сравниваете две ссылки на один и тот же кешированный объект.
При работе со строками мы можем просто сказать n00bs никогда не сравнивать их с ==
, как мы это делали все время. Но сравнение примитивов с ==
совершенно справедливо; трюк (благодаря автобоксингу) уверен, что значения действительно являются примитивами. Теперь компилятор объявит переменную как Integer
и будет использовать ее, как если бы она была int
; это означает, что мы должны проявлять более высокий уровень дисциплины и относиться к ней как к ошибке, когда кто-то делает это без уважительной причины.
Вместо того, чтобы называть их "сложными типами", вам лучше всего использовать мышью Integer, Double и т.д. как "классы", а int, double и т.д. как "примитивы".
Если вы выполняете какую-либо сложную математику, числовое представление на основе класса, такое как Integer и Double, будет громоздким и замедлит работу - многие математические операции могут выполняться только с помощью примитивов.
С другой стороны, если вы пытаетесь поместить свои номера в такие коллекции, как списки и карты, эти коллекции могут содержать только объекты - и, следовательно, вы должны использовать (или преобразовывать) классы, такие как Integer и Double.
Лично я использую примитивы, когда мне это удается, и только конвертировать в представления класса, такие как Integer, когда это время для ввода или вывода, а транспорт требует этих представлений.
Однако, если вы вообще не выполняете математику и вместо этого просто передаете значения прямо через свой код, вы можете сэкономить некоторые проблемы, обратившись к формам на основе класса (например, Integer).
Я не думаю, что существует какое-то правило как таковое. Я бы выбрал типы над примитивами (Integer over int), когда я пишу сигнатуры методов, Карты, коллекции, Объекты данных, которые передаются. Поэтому я все же хотел бы использовать Integer вместо int даже внутри методов и т.д. Но если вы считаете, что это слишком много проблем (чтобы ввести дополнительный "eger" ), тогда нормально использовать int для локальных переменных.
Если вы хотите установить атрибут на сеанс, вы должны использовать Object, например Integer, Boolean, String в сервлетах. Если вы хотите использовать значение, вы можете использовать примитивные типы. Объекты могут быть пустыми, но примитивы нет. И если вы хотите сравнить типы для примитивов, используйте ==, но объекты используют .equals, потому что в сравнении объектов == выглядит незначимые, если это те же объекты. И использование примитивов делает код быстрее.
Один случай, когда Integer
может быть предпочтительным, - это когда вы работаете с базой данных, где числовые записи разрешены равными нулю, поскольку вы не сможете представить нулевое значение с помощью int
.
Но, конечно, если вы делаете прямую математику, тогда int
будет лучше, чем другие говорили из-за интуитивности и меньше накладных расходов.
Я думаю, что это немного поздно, но я хотел бы добавить свое мнение на всякий случай.
в некоторых сценариях требуется использовать обертки, так как отсутствие значения отличается от значения по умолчанию.
например, для одного проекта, над которым я работал, на экране было поле, где пользователь мог ввести двойное значение, в бизнес-требовании четко указано, что если пользователь вводит 0, значение отличается от того, чтобы не вводить значение, и оставляя поле пустым, и это разница повлияет позже на другой модуль. поэтому в этом сценарии нам пришлось использовать объект Double, так как я не могу представить отсутствие значения с помощью примитива; так как примитив по умолчанию будет 0, что является допустимым вводом для поля.