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