Ловля NullPointerException
це дійсно проблематично , що потрібно зробити , так як вони можуть відбутися практично в будь-якому місці. Вийняти помилку дуже просто, зловити її випадково і продовжити так, ніби все нормально, приховуючи таким чином справжню проблему. З цим настільки складно мати справу, тому краще уникати взагалі. (Наприклад, подумайте про автоматичне розпакування нуля Integer
.)
Я пропоную вам використовувати Optional
клас замість цього. Це часто найкращий підхід, коли ви хочете працювати зі значеннями, які присутні або відсутні.
Використовуючи це, ви можете написати свій код так:
public Optional<Integer> m(Ws wsObject) {
return Optional.ofNullable(wsObject.getFoo()) // Here you get Optional.empty() if the Foo is null
.map(f -> f.getBar()) // Here you transform the optional or get empty if the Bar is null
.map(b -> b.getBaz())
.map(b -> b.getInt());
// Add this if you want to return null instead of an empty optional if any is null
// .orElse(null);
// Or this if you want to throw an exception instead
// .orElseThrow(SomeApplicationException::new);
}
Чому необов’язково?
Використання Optional
s замість null
значень, які можуть бути відсутніми, робить цей факт дуже зрозумілим і зрозумілим читачам, а система типу гарантує, що ви випадково не забудете про нього.
Ви також отримуєте доступ до методів роботи з такими значеннями зручніше, як map
іorElse
.
Чи відсутність помилки чи помилка?
Але також подумайте, чи це дійсний результат для проміжних методів повернення нуля чи це ознака помилки. Якщо це завжди помилка, то, ймовірно, краще кинути виняток, ніж повертати спеціальне значення, або для самих проміжних методів кидати виняток.
Можливо, додаткові опції?
Якщо, з іншого боку, відсутні значення значень проміжних методів дійсні, можливо, ви можете перейти до Optional
s для них?
Тоді ви можете використовувати їх так:
public Optional<Integer> mo(Ws wsObject) {
return wsObject.getFoo()
.flatMap(f -> f.getBar())
.flatMap(b -> b.getBaz())
.flatMap(b -> b.getInt());
}
Чому б не обов’язково?
Єдина причина, яку я можу подумати за те, що я не використовую, Optional
це те, що це справді критична частина коду, і якщо накладні витрати на збирання сміття виявляються проблемою. Це відбувається тому, що при Optional
кожному виконанні коду виділяється декілька об'єктів, і VM, можливо, не зможе їх оптимізувати. У такому випадку ваш оригінальний тест if може бути кращим.
null
чеками, оскількиwsObject.getFoo().getBar().getBaz().getInt()
це вже запах коду. Прочитайте, що таке "Закон про деметер" і віддавайте перевагу відповідному рефакторингу коду. Тоді проблема зnull
чеками також піде. І подумайте про використанняOptional
.