Я запізнююсь на гру, але для того, що вона варта, я хочу додати свої 2 центи. Вони суперечать дизайнерській метіOptional
, яку добре узагальнено у відповідь Стюарта Маркса , але я все одно переконаний у їх обґрунтованості (очевидно).
Використовуйте необов’язково скрізь
В загальному
Я написав цілу публікацію в блозі про використання,Optional
але в основному зводиться до цього:
- спроектуйте свої заняття, щоб уникнути факультативності, де це можливо
- у всіх інших випадках за замовчуванням слід використовувати
Optional
замістьnull
- можливо зробити винятки для:
- локальні змінні
- повернути значення та аргументи до приватних методів
- продуктивні критичні блоки коду (не здогадуйтесь, використовуйте профілер)
Перші два винятки можуть зменшити сприйняті витрати на обгортання та розгортання посилань у Optional
. Вони обрані таким чином, що нуль ніколи не може легально переходити межу від одного екземпляра до іншого.
Зауважте, що це майже ніколи не дозволить Optional
s в колекціях, що майже так само погано, як і null
s. Просто не робіть цього. ;)
Щодо ваших питань
- Так.
- Якщо перевантаження не є варіантом, так.
- Якщо інші підходи (підкласифікація, декорування, ...) не є варіантом, так.
- Будь ласка, ні!
Переваги
Це зменшує присутність null
s у вашій кодовій базі, хоча це не усуває їх. Але це навіть не головний пункт. Є й інші важливі переваги:
Уточнює наміри
Використання Optional
чітко виражає, що змінна є, ну, необов'язковою. Будь-який читач вашого коду або споживач вашого API буде побитий над головою, якщо там нічого не може бути, і перевірка потрібна перед тим, як отримати доступ до значення.
Знімає невизначеність
Без Optional
сенсу null
події незрозуміло. Це може бути юридичне представлення стану (див. Map.get
) Або помилка впровадження, як-от відсутня або невдала ініціалізація.
Це різко змінюється при постійному використанні Optional
. Тут вже поява null
означує наявність помилки. (Тому що якби значення було дозволено відсутнє, було Optional
б використано.) Це значно спрощує налагодження виключення з нульовим вказівником, оскільки на питання про значення цього null
значення вже відповіли.
Більше нульових перевірок
Тепер, коли вже нічого не може бути null
, це можна виконувати скрізь. З анотаціями, твердженнями або простими чеками, вам ніколи не доведеться думати про те, чи може цей аргумент чи той тип повернення бути недійсним. Це не може!
Недоліки
Звичайно, срібної кулі немає ...
Продуктивність
Встановлення значень (особливо примітивів) у додатковий екземпляр може погіршити продуктивність. У вузьких петлях це може стати помітним або навіть гіршим.
Зауважте, що компілятор, можливо, зміг би обійти додаткову посилання на короткочасне життя Optional
s. У Java 10 типи значень можуть додатково зменшити або зняти штраф.
Серіалізація
Optional
не є серіалізаційним, але вирішення не надто складне.
Інваріантність
Через інваріантність загальних типів на Java, певні операції стають громіздкими, коли фактичний тип значення висувається в аргумент загального типу. Тут наведено приклад (див. «Параметричний поліморфізм») .
Map<Character, String>
. Якщо немає ніякої заміни я можу використовувати це:Optional.ofNullable(map.get(c)).orElse(String.valueOf(c))
. Також зауважте, що необов'язково було вкрадено у Гуави, і він має набагато приємніший синтаксис:Optional.fromNullable(map.get(c)).or(String.valueOf(c));