Когда мне следует использовать класс-оболочку вместо примитивных типов? Или при каких обстоятельствах мне следует выбирать между типами обертки / примитивы?
Ответы:
Другие упоминали, что определенные конструкции, такие как Collections
require объектов, и что объекты имеют больше накладных расходов, чем их примитивные аналоги (память и упаковка).
Еще одно соображение:
Может быть удобно инициализировать объекты null
или отправлять null
параметры в метод / конструктор, чтобы указать состояние или функцию. Этого нельзя сделать с примитивами.
Многие программисты для обозначения этого инициализируют числа равными 0 (по умолчанию) или -1, но в зависимости от сценария это может быть неверным или вводящим в заблуждение.
Это также установит сцену для случая, NullPointerException
когда что-то используется неправильно, что гораздо удобнее для программистов, чем какая-то произвольная ошибка в дальнейшем.
Как правило, следует использовать примитивные типы, если только вы не по какой-либо причине нужен объект (например, для помещения в коллекцию). Даже тогда рассмотрите другой подход, который не требует объекта, если вы хотите максимизировать числовую производительность. Это рекомендуется в документации , и в этой статье показано, как автоматическая упаковка может вызвать большую разницу в производительности.
Integer
разборчивее, чем int
.
На мой взгляд, если члены моего класса являются переменными оболочки, он не полагается на значения по умолчанию, что является дружественным для разработчиков поведением.
1.
class Person {
int SSN ; // gets initialized to zero by default
}
2.
class PersonBetter {
Integer SSN; //gets initialized to null by default
}
В первом случае нельзя оставить значение SSN неинициализированным. Это может повредить, если вы не проверяете, было ли установлено значение перед попыткой его использования.
Во втором случае вы можете оставить SSN инициализированным значением null. Что может привести к NullPointerException, но это лучше, чем бессознательная вставка значений по умолчанию (ноль) в качестве SSN в базу данных всякий раз, когда вы пытаетесь использовать его без инициализации поля SSN.
PersonBuilder
исключение, если SSN не установлен до вызова «build» для получения Person
экземпляра. Я думаю, что такого рода вещи излишни, но это то, что язык Java продвигает для правильных шаблонов.
Я бы использовал типы обертки только в случае необходимости.
Используя их, вы ничего не выиграете, кроме того, что они есть Objects
.
И вы теряете накладные расходы на использование памяти и время, потраченное на упаковку / распаковку.
Практически я столкнулся с ситуацией, когда можно объяснить использование класса-оболочки.
Я создал класс обслуживания с long
переменной типа
long
- когда она не инициализирована, она будет установлена в 0 - это будет сбивать с толку пользователя при отображении в графическом интерфейсе. Long
- когда она не инициализирована, ей будет присвоено null
значение - это нулевое значение не будет отображаться в графическом интерфейсе.Это также относится к тем Boolean
случаям, когда значения могут быть более запутанными, когда мы используем примитив boolean
(поскольку значение по умолчанию - false).
Коллекции - типичный случай для простых объектов-оболочек Java. Однако вы можете подумать о том, чтобы придать Wrapper более конкретное значение в коде (объект значения).
ИМХО почти всегда есть преимущество в использовании объектов значений, когда все сводится к удобочитаемости и поддержке кода. Обертывание простых структур данных внутри объектов, когда у них есть определенные обязанности, часто упрощает код. Это очень важно в доменно-ориентированном дизайне .
Конечно, есть проблема с производительностью, но я склонен игнорировать ее, пока у меня не будет возможности измерить производительность с соответствующими данными и предпринять более целенаправленные действия в проблемной области. Также может быть легче понять проблему производительности, если код также прост для понимания.
производительность приложений, в которых преобладают численные вычисления, может значительно повысить эффективность использования примитивов.
Для примитивных типов используется оператор ==, но для оболочки предпочтительнее вызвать метод equals ().
«Примитивные типы считаются вредными», потому что они смешивают «процедурную семантику с единой объектно-ориентированной моделью».
Многие программисты для обозначения этого инициализируют числа равными 0 (по умолчанию) или -1, но в зависимости от сценария это может быть неверным или вводящим в заблуждение.
Если вы хотите использовать Коллекции, вы должны использовать классы Wrapper.
Примитивные типы используются для массивов. Также для представления данных, которые не имеют поведения, например счетчика или логического условия.
После автобокса граница «когда использовать примитив или оболочку» стала довольно нечеткой.
Но помните, что оболочки - это объекты, поэтому вы получаете все модные функции Java. Например, вы можете использовать отражение для создания объектов типа Integer, но не значений типа int. Классы-оболочки также имеют такие методы, как valueOf.
Если вы хотите создать тип значения. Что-то вроде ProductSKU или AirportCode.
Когда примитивный тип (строка в моих примерах) определяет равенство, вы захотите переопределить равенство.
Примитивные значения в Java не являются объектами. Чтобы управлять этими значениями как объектами, пакет java.lang предоставляет класс-оболочку для каждого примитивного типа данных.
Все классы Wrapper являются окончательными. Объекты всех классов оболочки, которые могут быть инициированы, являются неизменяемыми, что означает, что значение в объекте оболочки не может быть изменено.
Хотя класс void считается классом-оболочкой, но он не содержит никаких примитивных значений и не инициируется. У него нет общедоступного конструктора, он просто обозначает объект класса, представляющий ключевое слово void.