Причина Optional
додалася до Java в тому, що це:
return Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.findFirst()
.getOrThrow(() -> new InternalError(...));
чистіший за це:
Method matching =
Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.getFirst();
if (matching == null)
throw new InternalError("Enclosing method not found");
return matching;
Моя думка полягає в тому, що необов’язково було написано для підтримки функціонального програмування , яке було додано до Java одночасно. (Приклад наданий за допомогою блогу Брайана Гетца . Кращим прикладом може бути orElse()
метод, оскільки цей код все одно кине виняток, але ви отримаєте малюнок.)
Але зараз люди користуються Факультативом із зовсім іншої причини. Вони використовують це для усунення недоліків у мовній конструкції. Недолік у цьому: Немає можливості визначити, які з параметрів API та повернених значень дозволені як недійсні. Це може бути зазначено в javadocs, але більшість розробників навіть не пишуть javadocs для свого коду, і не багато хто перевірятиме javadocs, як вони пишуть. Таким чином, це призводить до великої кількості коду, який завжди перевіряє нульові значення, перш ніж використовувати їх, навіть незважаючи на те, що вони часто не можуть бути нульовими, оскільки вони вже перевірені дев'ять або десять разів вище стека викликів.
Я думаю, що була вирішена ця вада, тому що так багато людей, які бачили новий клас необов’язків, припускали, що його мета - додати ясність API. Ось чому люди задають питання на кшталт "чи повинні повернути необов’язкові користувачі?" Ні, вони, мабуть, не повинні, якщо ви не очікуєте, що геттер буде використаний у функціональному програмуванні, що дуже малоймовірно. Насправді, якщо поглянути на те, де додатково використовується Java API, то це переважно в класах Stream, які є ядром функціонального програмування. (Я не перевірив дуже ретельно, але класи Stream можуть бути єдиним місцем, де вони використовуються.)
Якщо ви плануєте використовувати геттер у трохи функціонального коду, може бути хорошою ідеєю мати стандартний і другий, який повертає необов’язково.
О, і якщо вам потрібно, щоб ваш клас був серіалізаційним, ви абсолютно не повинні користуватися факультативно.
Необов’язково - це дуже погане рішення вади API, оскільки: а) вони дуже багатослівні; б) вони ніколи не мали наміру вирішити цю проблему в першу чергу.
Набагато кращим рішенням вади API є перевірка нульовості . Це процесор анотацій, який дає змогу вказати, які параметри та значення повернення дозволені до нуля, анотувавши їх за допомогою @Nullable. Таким чином, компілятор може сканувати код і з'ясувати, чи передається значення, яке насправді є нульовим, до значення, де null заборонено. За замовчуванням він передбачає, що нічого не можна вважати нульовим, якщо це так не зазначається. Таким чином, вам не доведеться турбуватися про нульові значення. Передача нульового значення параметру призведе до помилки компілятора. Тестування об'єкта на null, який не може бути null, створює попередження компілятора. Ефект цього полягає в зміні NullPointerException з помилки виконання на помилку часу компіляції.
Це все змінює.
Що стосується ваших людей, не використовуйте необов’язково. І спробуйте спроектувати свої класи, щоб жоден з членів не міг бути нульовим. І, можливо, спробуйте додати у свій проект Checker Nullness і оголосити ваші геттери та параметри setter @Nullable, якщо вони цього потребують. Я це робив лише з новими проектами. Це, мабуть, створює багато попереджень у існуючих проектах, написаних з безліччю зайвих тестів на нуль, тому може бути важко доопрацювати. Але це також зловить багато клопів. Я це люблю. Мій код набагато чистіший і надійніший через нього.
(Існує також нова мова, яка стосується цього. Kotlin, який компілює в байтний код Java, дозволяє вам вказати, чи може об'єкт бути недійсним, коли ви декларуєте його. Це більш чистий підхід.)
Додаток до оригінальної публікації (версія 2)
Задумавшись, я неохоче прийшов до висновку, що повернути Факультативно прийнятно за однієї умови: щоб отримане значення насправді було недійсним. Я бачив багато коду, коли люди звичайно повертають необов’язково від одержувачів, які не можуть повернути нуль. Я вважаю це дуже поганою практикою кодування, яка лише додає складності коду, що робить помилки більш імовірними. Але коли повернене значення може бути фактично недійсним, продовжуйте і загортайте його в необов’язковий.
Майте на увазі, що методи, розроблені для функціонального програмування та потребують посилання на функцію, будуть (і повинні) бути написані у двох формах, в одній з яких використовується Необов'язково. Наприклад, Optional.map()
і Optional.flatMap()
обидва беруть посилання на функції. Перший посилається на звичайний геттер, а другий - той, що повертає необов’язково. Таким чином, ви не робите нікому прихильності, повертаючи необов’язково, коли значення не може бути нульовим.
Сказавши все це, я все ще бачу підхід, який застосовує перевірка нульовості, є найкращим способом боротьби з нулями, оскільки вони перетворюють NullPointerExceptions з помилок виконання для компіляції помилок часу.