Коли використовувати клас обгортки та примітивний тип


98

Коли я повинен перейти до класу обгортки порівняно з примітивними типами? Або за якої обставини я повинен вибрати між обгортковими / примітивними типами?


1
w3resource.com/java-tutorial/java-wrapper-classes.php Ця стаття буде корисною для цієї дискусії.
pankaj

Відповіді:


69

Інші згадували, що деякі конструкції, такі як Collections вимагають об'єктів, і що об'єкти мають більше накладних витрат, ніж їх примітивні аналоги (пам'ять та бокс).

Іншим фактором є:

Це може бути зручно ініціалізувати Об’єкти nullабо надіслати nullпараметри в метод / конструктор для позначення стану або функції. Цього не можна зробити за допомогою примітивів.

Багато програмістів ініціюють цифри до 0 (за замовчуванням) або -1, щоб це позначити, але залежно від сценарію це може бути неправильним або оманливим.

Це також створить сцену, NullPointerExceptionколи щось використовується неправильно, що набагато зручніше для програмістів, ніж якась довільна помилка.


15
Msgstr "Це може бути зручно ініціалізувати Об'єкти для нуля". Це не може бути корисним, оскільки це неправильно, якщо поле є необов’язковим, ви повинні вказати це явно.
Eddie Jamsession

8
lol @EddieJamsession дякую, я ніколи більше не ініціюю значення null. (pfffft)
пстантон

@EddieJamsession Якщо ініціалізація Об'єктів до нуля як спосіб індикації помилки при встановленні фактичного значення не вдалася, як би Ви пропонували вловити цю проблему? О, я щойно зрозумів, набираючи це: винятки. NullPointerException занадто загальний; було б краще використовувати дуже конкретні спеціальні винятки, щоб вказати, що пішло не так. Добре, я буду робити це відтепер ...
klaar

1
@EddieJamsession Ознайомившись із цим питанням, я натрапив на поняття необов’язкового об’єкта. Правильно.
klaar

18

Як правило, ви повинні використовувати примітивні типи, якщо вам не потрібен об'єкт з якихось причин (наприклад, для розміщення в колекції). Навіть тоді, розгляньте інший підхід, який не вимагає об’єкта, якщо ви хочете максимізувати числові показники. Це зазначено в документації , і ця стаття демонструє, як автобокс може спричинити велику різницю в продуктивності.


3
Показник продуктивності не такий великий, щоб розбірливість / надійність коду відійшла на другий план.
pstanton

2
По-перше, правильне використання примітивів не зробить ваш код нечитабельним. По-друге, показник ефективності в деяких випадках є значним. Абсурдно стверджувати, що ніколи не буває.
Метью Флашен

1
@pstanton: поясніть, будь ласка, як Integerце читабельніше, ніж int.
Stephen C

У багатьох випадках Integer є не більш розбірливим, ніж int, і в цих випадках я завжди буду використовувати int, або якщо я знаю, що певна змінна НІКОЛИ не буде нульовою, я буду використовувати int, оскільки int, як ви вказали, трохи ефективніший. Однак у багатьох випадках іншому програмісту легше зрозуміти стан змінної, коли використовується об'єкт, оскільки його можна ініціалізувати нулем, щоб вказати, що він не готовий. Наприклад, якщо у вас є незбережений запис бази даних, який має унікальний збільшуючий числовий ідентифікатор, чи повинен цей ідентифікатор бути 0, -1 або нульовим, перш ніж йому буде присвоєно дійсний ідентифікатор? У такому випадку об’єкти краще.
pstanton

щодо продуктивності - в особливих випадках показник продуктивності може бути значним, тобто якщо ви створюєте безліч цих Об'єктів дуже швидко або якщо багато багато з них накопичуються протягом певного періоду часу. Однак я би очікував, що гідний програміст зможе виявити ці особливі випадки або уникнути, або внести відповідні зміни. Я ніколи не говорив, що це НІКОЛИ суттєво, проте загалом кажучи, це не так.
pstanton

12

На мій погляд, якщо члени мого класу є змінними обгортки, це не покладається на значення за замовчуванням, що є доброзичливою поведінкою розробника.

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.


3
Шаблон конструктора призначений для того, щоб обійти це. У цьому сценарії ви робите, PersonBuilderщо видає виняток, якщо SSN не встановлений до виклику "build", щоб отримати Personекземпляр. Я думаю, що подібні речі є надмірними, але саме це сприяє мові Java для правильних зразків.
Сенді Чепмен

8

Я б використовував лише типи обгортки, якщо вам потрібно.

Використовуючи їх, ви не отримуєте багато, крім того, що вони є Objects.

І ви втрачаєте накладні витрати на пам'ять та витрачений час на бокс / розпакування.


4
ви можете не багато виграти, але й багато не втратите. якщо ви не працюєте на пальмовому пілоті 1990-х.
pstanton

Той факт, що вони є Об'єктами, також дає їм набагато більше контексту та інкапсуляції, ніж як звичайний примітив. Тож ви насправді можете отримати багато чого залежно від того, для чого призначені ці примітиви та де вони використовуються.
aberrant80,

4

Практично я зіткнувся з ситуацією, коли використання класу обгортки можна пояснити.

Я створив клас обслуговування, який мав longзмінну типу

  1. Якщо змінна має тип long - коли вона не ініціалізована, для неї буде встановлено значення 0 - це буде заплутати користувача при відображенні в графічному інтерфейсі
  2. Якщо змінна має тип Long- якщо вона не ініціалізована, для неї буде встановлено значення null- це нульове значення не відображатиметься в графічному інтерфейсі.

Це стосується і Booleanтих випадків, коли значення можуть бути більш заплутаними, коли ми використовуємо примітив boolean(оскільки значення за замовчуванням - false).


3

Колекції - типовий випадок для простих обгорткових об'єктів Java. Однак ви можете подумати про надання Wrapper більш конкретного значення в коді (об'єкт значення).

IMHO майже завжди має перевагу використовувати об’єкти вартості, коли це зводиться до читабельності та підтримання коду. Обгортання простих структур даних всередині об’єктів, коли вони мають певні обов’язки, часто спрощує код. Це те, що є дуже важливим у домен-керованому дизайні .

Звичайно, є проблема продуктивності, але я, як правило, ігнорую це, поки у мене не буде можливості виміряти ефективність за допомогою належних даних і робити більш спрямовані дії щодо проблемної області. Також може бути простіше зрозуміти проблему продуктивності, якщо код також легко зрозуміти.


3

ефективність програм, в яких переважають чисельні обчислення, може отримати значну користь від використання примітивів.

примітивні типи, використовується оператор ==, але для обгортки кращим вибором є виклик методу equals ().

"Первісні типи вважаються шкідливими" оскільки вони поєднують "процедурну семантику в інакше єдину об'єктно-орієнтовану модель.

Багато програмістів ініціюють цифри до 0 (за замовчуванням) або -1, щоб це позначити, але залежно від сценарію це може бути неправильним або оманливим.


1

Якщо ви хочете використовувати колекції, ви повинні використовувати класи Wrapper.

Первісні типи, використовуються для масивів. Крім того, для представлення даних, які не мають поведінки, наприклад, лічильник або логічна умова.

Починаючи з автобоксу, межа "коли використовувати примітив або обгортку" стала досить нечіткою.

Але пам’ятайте, обгортки - це об’єкти, тому ви отримуєте всі вишукані функції Java. Наприклад, ви можете використовувати рефлексію для створення цілих об'єктів, але не значень int. Класи обгортки також мають такі методи, як valueOf.


Крім колекцій, я не повинен використовувати класи обгортки? Як щодо того, щоб використовувати його для звичайного оголошення, як Integer i = new Integer (10); Чи добре робити так?
Гопі

автобокс дозволяє зробити Integer i = 10;
Том

1
Ні, Шрі. Якщо у вас немає вимоги, щоб я був об'єктом, не робіть це.
Метью Флашен

Автобокс розпакує вищезазначене i до int i = 10 або Integer i = 10?
Гопі

3
int pi = нове ціле число (10); працює. Ціле число oi = 10; працює. int ni = нуль; не працює. LHS перетворюється на те, що вимагає RHS.
pstanton

0

Якщо ви хочете створити тип значення. Щось на зразок ProductSKU або AirportCode.

Коли примітивний тип (рядок у моїх прикладах) визначає рівність, ви захочете замінити рівність.


5
рядок не є примітивним
pstanton

2
все ще є вагомі причини, щоб обернути тип значення, що містить рядок як базовий об’єкт.
Chris Missal

ваша відповідь просто не має сенсу. я не впевнений, що ви говорите. Я погоджуюсь з вашим коментарем, однак, класи обгортки - це гарна ідея, якщо вони покращують читабельність.
pstanton

Типи цінностей або об'єкти значень повинні створюватися та бути незмінними. Наприклад, не було б сенсом створювати об'єкт "CountryCode", наприклад: new CountryCode ("USA"), а потім створювати інший об'єкт таким же чином, де пізніше вони будуть різними. Для початку це просто струни, але вони мають значення. Використовуючи рядки, ви можете їх змінювати (додаючи більше даних тощо), але вони більше не будуть рівними. Див. Цю статтю для кращого опису того, що я намагаюся пояснити :) Сподіваюсь, це має сенс c2.com/cgi/wiki?ValueObject
Кріс

0

Первісні значення в Java не є об'єктом. Для того, щоб маніпулювати цими значеннями як об'єктом, пакет java.lang надає клас обгортки для кожного примітивного типу даних.

Усі класи Wrapper є заключними. Об'єкт усіх класів обгортки, які можна ініціювати, є незмінними, що означає, що значення в об'єкті обгортки не може бути змінено.

Хоча клас void вважається класом обгортки, але він не обертає жодних примітивних значень і не може ініціюватися. Він не має конструктора public, він просто позначає об'єкт класу, що представляє ключове слово void.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.