Ваша основна помилка в тому, що ви все ще думаєте в більш процедурному плані. Це не мається на увазі як критика вас як особистості, це лише спостереження. Мислення в більш функціональному плані пов'язане з часом і практикою, а тому методи єПроявляйте і виглядайте як найбільш очевидні правильні речі, за якими потрібно закликати вас. Ваша вторинна незначна помилка - це створення Факультативного всередині вашого методу. Необов’язковий покликаний допомогти документувати, що щось може або не може повернути значення. Ви можете нічого не отримати.
Це призвело до того, що ви пишете ідеально розбірливий код, який здається цілком розумним, але вас спокусили мерзенні спокусниці-близнюки, які отримують і є присутній.
Звичайно, питання швидко стає "чому вони присутня і туди навіть?"
Що багато хто тут пропускає, це те, що isPresent () - це те, що це не те, що створено для нового коду, написаного людьми повністю на борту з тим, наскільки корисні лямбди, які люблять готівку, і яким подобається функціональна річ.
Однак це дає нам кілька (двох) добрих, чудових, гламурних (?) Переваг:
- Це полегшує перехід застарілого коду до використання нових функцій.
- Це полегшує криві навчання за вибором.
Перший досить простий.
Уявіть, у вас є API, який виглядав так:
public interface SnickersCounter {
/**
* Provides a proper count of how many snickers have been consumed in total.
*/
public SnickersCount howManySnickersHaveBeenEaten();
/**
* returns the last snickers eaten.<br>
* If no snickers have been eaten null is returned for contrived reasons.
*/
public Snickers lastConsumedSnickers();
}
І у вас був спадковий клас, використовуючи цей як такий (заповніть пробіли):
Snickers lastSnickers = snickersCounter.lastConsumedSnickers();
if(null == lastSnickers) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers);
}
Надуманий приклад, напевне. Але візьми зі мною тут.
Зараз запущена Java 8, і ми намагаємося вийти на борт. Отже, одна з речей, яку ми робимо, - це те, що ми хочемо замінити старий інтерфейс чимось, що повертає необов’язково. Чому? Тому що, як хтось уже милостиво згадував:
Це виймає здогадки про те, чи може щось бути недійсним, на
це вже вказували інші. Але зараз у нас є проблема. Уявіть, у нас є (вибачте, поки я натиснув alt + F7 невинним методом), 46 місць, де цей метод називається добре перевіреним спадковим кодом, який робить відмінну роботу інакше. Тепер ви повинні оновити все це.
ЦЕ це місце, де світить.
Тому що зараз: Snickers lastSnickers = snickersCounter.lastConsumedSnickers (); if (null == lastSnickers) {киньте новий NoSuchSnickersException (); } else {Consumer.giveDiabetes (lastSnickers); }
стає:
Optional<Snickers> lastSnickers = snickersCounter.lastConsumedSnickers();
if(!lastSnickers.isPresent()) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers.get());
}
І це проста зміна, яку ви можете дати новому молодшому: Він може зробити щось корисне, і він одночасно вивчить базу коду. безпрограшний. Зрештою, щось подібне до цієї моделі досить поширене. І тепер вам не доведеться переписувати код, щоб використовувати лямбда або що-небудь інше. (У цьому конкретному випадку це було б банально, але я залишаю придумувати приклади, коли це буде важко як вправу для читача.)
Зауважте, що це означає, що так, як ви це зробили, це по суті спосіб поводження зі застарілим кодом, не роблячи дорогих переписувань. То як бути з новим кодом?
Що ж, у вашому випадку, де ви просто хочете щось надрукувати, ви просто зробите:
snickersCounter.lastConsumedSnickers (). ifPresent (System.out :: println);
Що досить просто і абсолютно зрозуміло. Сенс, який повільно кидається на поверхню, полягає в тому, що існують випадки використання для get () та isPresent (). Вони там, що дозволяють механічно змінювати існуючий код, щоб використовувати новіші типи, не надто замислюючись про це. Отже, те, що ви робите, неправильно керується такими способами:
- Ви викликаєте метод, який може повернути нуль. Правильна думка полягала б у тому, що метод повертає null.
- Ви використовуєте застарілі методи бандайдів для боротьби з цим необов’язковим, замість того, щоб використовувати нові смачні методи, що містять лямбда-химерність.
Якщо ви хочете використовувати Необов’язково як просту перевірку безпеки на нуль, то, що ви повинні зробити, це просто:
new Optional.ofNullable(employeeServive.getEmployee())
.map(Employee::getId)
.ifPresent(System.out::println);
Звичайно, гарна версія цього виглядає так:
employeeService.getEmployee()
.map(Employee::getId)
.ifPresent(System.out::println);
До речі, хоча це аж ніяк не потрібно, я радимо використовувати новий рядок за операцією, щоб було легше читати. Легко читати і розуміти, щоби лаконічніше було в будь-який день тижня.
Це, звичайно, дуже простий приклад, коли легко зрозуміти все, що ми намагаємось зробити. У реальному житті це не завжди так просто. Але зауважте, як у цьому прикладі ми виражаємо свої наміри. Ми хочемо отримати працівника, отримати його посвідчення та, якщо можливо, роздрукувати його. Це другий великий виграш із Факультативом. Це дозволяє нам створити більш чіткий код. Я також думаю, що робити такі речі, як створення методу, який робить купу речей, щоб ви могли подати його на карту, взагалі хороша ідея.