Чому не слід використовувати аргументи Java 8 Необов’язково


392

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

public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
    // my logic
}

Багато веб-сторінок вказують, що необов'язково не слід використовувати як аргументи методу. Маючи це на увазі, я міг би використати наступний метод підпису та додати чіткий коментар Javadoc, щоб вказати, що аргументи можуть бути недійсними, сподіваючись, що майбутні технічні працівники прочитають Javadoc і тому завжди проводять перевірку нуля перед використанням аргументів (рішення 2) :

public int calculateSomething(String p1, BigDecimal p2) {
    // my logic
}

Крім того, я міг би замінити свій метод чотирма загальнодоступними методами, щоб забезпечити приємніший інтерфейс і зробити його більш очевидним, що p1 і p2 не є обов'язковими (рішення 3):

public int calculateSomething() {
    calculateSomething(null, null);
}

public int calculateSomething(String p1) {
    calculateSomething(p1, null);
}

public int calculateSomething(BigDecimal p2) {
    calculateSomething(null, p2);
}

public int calculateSomething(String p1, BigDecimal p2) {
    // my logic
}

Тепер я намагаюся написати код класу, який використовує цю логіку для кожного підходу. Я спочатку отримую два вхідні параметри з іншого об'єкта, який повертає Optionals, а потім я викликаю calculateSomething. Тому, якщо використовується рішення 1, викликовий код буде виглядати приблизно так:

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);

якщо використовується рішення 2, код виклику виглядатиме так:

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));

якщо застосовано рішення 3, я міг би використати код вище або можу використовувати наступне (але це значно більше коду):

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result;
if (p1.isPresent()) {
    if (p2.isPresent()) {
        result = myObject.calculateSomething(p1, p2);
    } else {
        result = myObject.calculateSomething(p1);
    }
} else {
    if (p2.isPresent()) {
        result = myObject.calculateSomething(p2);
    } else {
        result = myObject.calculateSomething();
    }
}

Отже, моє питання: Чому вважається поганою практикою використовувати Optionals в якості аргументів методу (див. Рішення 1)? Це виглядає як найбільш читабельне рішення для мене і робить найбільш очевидним, що параметри можуть бути порожніми / недійсними для майбутніх обслуговуючих служб. (Мені відомо, що дизайнери Optionalзадумали його використовувати лише як тип повернення, але я не можу знайти жодних логічних причин не використовувати його у цьому сценарії).


16
Якщо ви використовували необов'язкові, чи не доведеться вам перевіряти, чи необов'язковий переданий параметр не є null ?
biziclop

17
Так, але для інших, хто підтримує код у майбутньому, стане очевидним, що параметр може бути порожнім / null, тому потенційно уникнути виключення нульового вказівника в майбутньому
Ніл Стівенс

1
Ого. Нульові аргументи передаються методу? Ось так Visual Basic. Який принцип він порушує? SRP (можливо). Це також порушує інший принцип, ім'я якого залишає мене позбавленим, йде по лінії передачі ТІЛЬКИ необхідної інформації для того, щоб метод чи функція виконувала свою роботу.
Світлий

20
Все теоретично, можливо, є недійсним, як і кожен метод у бібліотеці, можливо, викликає System.exit (0). Ви не можете перевірити тис і не повинні перевіряти це. Все, що вам доведеться робити весь час, що ви насправді не повинні (майже) ніколи не робити. Як і зробити всі параметри остаточними. Нехай ваші інструменти допоможуть вам запобігти зміні значень параметрів або забути ініціалізувати поля замість того, щоб зробити ваш код нечитабельним тисячами фіналів і стільки ж нульових перевірок.
йоман

6
Насправді просто використовуйте примітки NonNull / Nullable. Це те, що ви шукаєте в цій ситуації, а не необов’язково.
Білл К

Відповіді:


202

О, ці стилі кодування слід сприймати з трохи солі.

  1. (+) Передача факультативного результату іншому методу без будь-якого семантичного аналізу; залишати це методом, цілком гаразд.
  2. (-) Використання факультативних параметрів, що викликають умовну логіку всередині методів, є буквально протипродуктивним.
  3. (-) Необхідність упаковки аргументу в необов'язковій формі є неоптимальною для компілятора і робить непотрібне обгортання.
  4. (-) У порівнянні з нульовими параметрами Необов’язково коштує дорожче.

Загалом: необов'язково об'єднує два стани, які треба розплутати. Тому краще підходить для результату, ніж для введення даних, для складності потоку даних.


38
На насправді, маючи Optionalпараметр являє собою один з трьох станів: а nullнеобов'язкові, непорожньої Optionalз isPresent() == falseі непорожньої Optionalобгорткового фактичним значенням.
biziclop

16
@biziclop так, неминучий момент вже критикували. Але наміром є лише ненульові вирази. Те, що не зайняло багато часу, почути пораду уникати Необов’язково в деяких випадках теж досить іронічно. @NotNull Optional.
Joop Eggen

80
@biziclop Зауважте, що якщо ви Optionalвзагалі використовуєте, то стан 1 ( nullнеобов'язково) зазвичай вказує на помилку програмування, тому ви можете також не впоратися з цим (просто нехай це кине а NullPointerException)
user253751

50
"недооптимальний для компілятора", "Порівняно з змінними параметрами необов'язково коштує дорожче" - ці аргументи можуть бути дійсними для мови C, а не для мови Java. Java-програмісти повинні зосередитись на чистому коді, переносимості, тестабельності, хорошій архітектурі, модульності тощо, а не на "Необов’язково коштує дорожче, ніж нульове посилання". І якщо ви виявите, що вам потрібно зосередитись на мікрооптимізаціях, тоді вам краще пропустити об’єкти, списки, загальну інформацію та перейти на масиви та примітиви (я не хочу тут ображатись, я просто ділюсь своєю думкою) .
Kacper86

15
"Неоптимальний для компілятора": Передчасна оптимізація - корінь усього зла ... якщо ви не пишете критичний код продуктивності (що часто буває при спробі вказати чистий інтерфейс), це не повинно викликати занепокоєння.
Мохан

165

Кращий пост я бачив на цю тему було написано Даніелем Ольшевським :

Хоча це може бути заманливо вважати необов'язковим для не обов'язкових параметрів методу, таке рішення блідне порівняно з іншими можливими альтернативами. Щоб проілюструвати проблему, вивчіть таку декларацію конструктора:

public SystemMessage(String title, String content, Optional<Attachment> attachment) {
    // assigning field values
}

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

SystemMessage withoutAttachment = new SystemMessage("title", "content", Optional.empty());
Attachment attachment = new Attachment();
SystemMessage withAttachment = new SystemMessage("title", "content", Optional.ofNullable(attachment));

Замість того, щоб надати чіткість, фабричні методи класу Факультатив лише відволікають читача. Зауважте, що є лише один необов'язковий параметр, але уявіть, що він має два або три. Дядько Боб точно не пишається таким кодом 😉

Коли метод може приймати необов'язкові параметри, бажано прийняти добре перевірений підхід і спроектувати такий випадок, використовуючи метод перевантаження. У прикладі класу SystemMessage, декларування двох окремих конструкторів перевершує використання Optional.

public SystemMessage(String title, String content) {
    this(title, content, null);
}

public SystemMessage(String title, String content, Attachment attachment) {
    // assigning field values
}

Ця зміна робить клієнтський код набагато простішим та легшим для читання.

SystemMessage withoutAttachment = new SystemMessage("title", "content");
Attachment attachment = new Attachment();
SystemMessage withAttachment = new SystemMessage("title", "content", attachment);

10
Копіювати та вставляти дуже багато, коли актуальні лише один або два абзаци.
Гаррет Вілсон

47
На жаль, це пояснення не стосується проблеми, коли абонент, наприклад, аналіз деякої інформації може бути необов’язковим. При перевантаженні методу (як рекомендовано вище) викликовий код повинен говорити: "Чи присутній X? Якщо це так, я зателефоную перевантаженому методу A. Чи є Y? Я повинен викликати перевантажений метод B. Якщо X і Y присутні, мені доведеться викликати перевантажений метод C. " І так далі. На це може бути хороша відповідь, але це пояснення "чому" не охоплює цього.
Гаррет Вілсон

9
Крім того, що стосується колекцій, то чітка різниця між порожньою колекцією та без колекції. Наприклад, кеш-пам'ять. Це була помилка кеша? порожній необов’язковий / null. Чи був хіт кешу, який, здається, порожня колекція? повний факультативний / колекція
Аякс

1
@Ajax Я думаю, що ви неправильно розумієте статтю. Вони цитують точку, яку відстоює книга " Ефективна Java" , в якій сказано, що коли тип повернення методу - це Колекція (а не довільний об'єкт, як кеш повертається), тоді вам слід віддавати перевагу поверненню порожньої колекції замість nullабо Optional.
Гілі

4
Звичайно, вам слід віддавати перевагу , але ви не завжди маєте контроль над яким-небудь кодом, і, в дуже реальному сенсі, ви можете розмежувати "є значення, і це порожня колекція" проти "немає значення, визначене (поки) ". Оскільки "магічний нуль" - це також відлякує практику, ви, розробник, вирішувати вибрати найменш поганий варіант. Я віддаю перевагу порожній необов'язково представляти пропущення кешу замість порожньої колекції, оскільки фактичне кешоване значення може бути порожньою колекцією.
Аякс

86

Практично немає вагомих причин не використовувати Optionalв якості параметрів. Аргументи проти цього покладаються на аргументи влади (див. Брайан Гец - його аргумент полягає в тому, що ми не можемо застосувати необов'язкові необов'язкові) або щоOptional аргументи можуть бути недійсними (по суті той же аргумент). Звичайно, будь-яка посилання на Java може бути нульовою, нам потрібно заохочувати правила, які виконує компілятор, а не пам'ять програмістів (що проблематично і не масштабує).

Функціональні мови програмування заохочують Optionalпараметри. Одним з найкращих способів використання цього є наявність декількох необов’язкових параметрів та liftM2використання функції, припускаючи, що параметри не порожні та повернення необов’язкового (див. Http://www.functionaljava.org/javadoc/4.4/functionaljava/fj/ data / Option.html # liftM2-fj.F- ). На жаль, Java 8 реалізувала дуже обмежену бібліотеку, яка підтримує необов'язковість.

Як програмісти Java, ми повинні використовувати null лише для взаємодії зі застарілими бібліотеками.


3
Як щодо використання @Nonnullта @Nullableз javax.annotation замість цього? Я широко використовую їх у бібліотеці, яку я розвиваю, і підтримка IDE (IntelliJ) дуже хороша.
Rogério

1
Це добре, але ви повинні використовувати цю анотацію скрізь, і вам потрібна бібліотека для підтримки таких методів, як map, flatMap / bind, liftM2, послідовність тощо.
Марк Перрі

14
Мови функціонального програмування заохочують необов'язкові параметри. Потрібне цитування. Більшість функцій не повинні приймати необов'язково; натомість тяга до розгляду (використання відповідних функцій вищого порядку) з наявністю або відсутністю значення є на абонента відповідної функції.
jub0bs

5
Це. Дійсно, жодна з відповідей не є достатньо переконливою, і жодна з них не дає відповіді на це конкретне запитання, "чому використання факультативних параметрів як параметрів методу вважається поганою практикою, тоді як анотування параметрів методу з" @NonNullцілком чудово ", якщо вони служать одній і тій же цілі по-різному?" Для мене є лише один аргумент, який має хоч якийсь сенс: "Необов’язково слід використовувати для надання кращих API, які мають чіткий тип повернення. Однак для аргументів методу можна використовувати перевантажені функції". - все-таки я не думаю, що це аргумент, який є досить сильним.
Utku Özdemir

1
Звичайно, переважніше нульове значення, але ще більше переваги - це не потрібно в першу чергу багато необов’язкових значень, оскільки хороший дизайн: D
yeoman

12

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

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

  • ви хочете, щоб ваша функція використовувалася спільно з іншим API, який повертає Optional
  • Ваша функція повинна повертати щось інше, ніж порожнє, Optionalякщо задане значення порожнє
  • Ви думаєте, що Optionalце так приголомшливо, що той, хто використовує ваш API, повинен вимагати дізнатися про нього ;-)

10

Зображення з Optional- це одна, щоб уникнути повернення null . Все одно цілком можливо пройтиnull до методу.

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

public int calculateSomething(@NotNull final String p1, @NotNull final String p2) {}

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

1
@dwegener Так, але Optionalце також не вирішує проблему, звідси і моя пропозиція щодо анотацій.
Макото

2
Набагато складніше ігнорувати Необов’язково, ніж ігнорувати примітку, яку ви помітите лише у тому випадку, коли прочитаєте документи / джерело або якщо ваш інструментарій може її зафіксувати (статичний аналіз не завжди може визначити нульовість правильно).
Аякс

Зауважте, що @Nullable не може означати, що ви "приймаєте" null як дійсне значення, тобто не кидаєте жодного винятку. Це може просто означати, що ви захищаєтеся від цієї справи, але все ж кинете виняток (Це семантика Findbugs). Таким чином, ви можете ввести неоднозначність з такими примітками замість ясності.
tkruse

Я не впевнений, яка там двозначність @ user2986984. "Не обробка нуля" могла лише реально означати, що викид викинуто.
Макото

7

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

Це, як було сказано, об'єднувати методи разом, які беруть / повертають необов'язково, - це розумно робити, наприклад, може, монада.


7
Неможливо також повернути значення і поля, які є нульовими? Тож Optionalбезглуздо цілком?
Samuel Edwin Ward

6

Перевірте JavaDoc в JDK10, https://docs.oracle.com/javase/10/docs/api/java/util/Otional.html , додано примітку API:

Примітка API: Необов’язково в першу чергу призначений для використання як тип повернення методу, коли є явна потреба представляти "немає результату" і де використання нуля, ймовірно, спричинить помилки.


4

Я вважаю, що необов'язково повинна бути монадою, і це не можливо в Java.

У функціональному програмуванні ви маєте справу з функціями чистого та вищого порядку, які беруть і складають свої аргументи лише на основі "типу доменного бізнесу". Композиція функцій, що живляться або про обчислення яких слід повідомити у реальному світі (так звані побічні ефекти), вимагає застосування функцій, які забезпечують автоматичне розпакування значень із монад, що представляють зовнішній світ (стан, конфігурація, Майбутні, Можливо, Або, Письменник тощо ...); це називається підйомом. Ви можете думати про це як про своєрідне розділення проблем.

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


3

Ще одна причина, щоб бути обережною при передачі Optionalпараметра as, полягає в тому, що метод повинен виконувати одну річ ... Якщо ви передасте Optionalпарам, ви могли б віддати перевагу більше ніж одне, це могло б бути аналогічним передачі булевої парами.

public void method(Optional<MyClass> param) {
     if(param.isPresent()) {
         //do something
     } else {
         //do some other
     }
 }

Я думаю, що це не вагомі причини. Таку ж логіку можна застосувати і для перевірки, чи параметр є нульовим, коли не використовується необов'язковий. Насправді, if(param.isPresent())це не найкращий підхід до використання Необов’язково, натомість ви можете використовувати:param.forEach(() -> {...})
hdkrus

Мені також не подобається ідея передавати незмінні парами. У будь-якому випадку, я сказав, що ви можете надавати перевагу, звичайно, є винятки, якими ви можете скористатися, це залежить від вас, просто обережно використовуйте, ось і все. Не існує жодного правила, яке застосовується для всіх сценаріїв.
Пау

2

Прийняття необов'язкових як параметрів спричиняє непотрібне обгортання на рівні виклику.

Наприклад у випадку:

public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {}

Припустимо, у вас є дві ненульові рядки (тобто повернуті з якогось іншого методу):

String p1 = "p1"; 
String p2 = "p2";

Ви змушені загортати їх у необов’язкові, навіть якщо знаєте, що вони не порожні.

Це стає ще гірше, коли вам доведеться складати інші "відображаються" структури, тобто. Ебі :

Either<Error, String> value = compute().right().map((s) -> calculateSomething(
< here you have to wrap the parameter in a Optional even if you know it's a 
  string >));

посилання:

Методи не повинні сподіватися на параметр як параметр; це майже завжди запах коду, який вказував на витік контрольного потоку від абонента до виклику, він повинен нести відповідальність за перевірку вмісту параметра

реф. https://github.com/teamdigitale/digital-citizenship-functions/pull/148#discussion_r170862749


1

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


1

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


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

1

Необов’язково не розраховані на цю мету, як це добре пояснив Брайан Гец .

Ви завжди можете використовувати @Nullable для позначення того, що аргумент методу може бути нульовим. Використання необов'язкового дійсно не дає змоги більш чітко писати логіку методу.


5
Вибачте, але я не можу погодитися з аргументом "не було розроблено" або "хтось рекомендує проти цього". Інженером ми повинні бути конкретними. Використання @Nullable набагато гірше, ніж використання Опціонального, оскільки необов'язкові набагато більш багатослівні з точки зору API. Я не бачу жодних вагомих причин проти використання необов'язкових як аргументів (за умови, що ви не хочете використовувати перевантаження методом)
Kacper86

0

Ще один підхід - це те, що ти можеш зробити

// get your optionals first
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();

// bind values to a function
Supplier<Integer> calculatedValueSupplier = () -> { // your logic here using both optional as state}

Після того як ви побудуєте функцію (постачальник у цьому випадку), ви зможете пропустити це навколо як будь-яку іншу змінну і зможете викликати її за допомогою

calculatedValueSupplier.apply();

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

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


0

Спочатку я також вважав за краще передавати необов'язкові параметри, але якщо перейти з точки зору дизайнера API на перспективу API-користувача, ви побачите недоліки.

Для вашого прикладу, коли кожен параметр є необов'язковим, я б запропонував змінити метод обчислення на власний клас, як слід:

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();

MyCalculator mc = new MyCalculator();
p1.map(mc::setP1);
p2.map(mc::setP2);
int result = mc.calculate();

0

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

Що я робив, що добре послужило мені як правило. Потрібно використовувати необов'язкові для типів повернення та використовувати лише Параметри як параметри, якщо я вимагаю як значення Необов’язкового, так і погоди, чи не необов'язковий, має значення в методі.

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


0

Це тому, що ми маємо різні вимоги до користувача API та розробника API.

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

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


0

Перш за все, якщо ви використовуєте метод 3, ви можете замінити ці останні 14 рядків коду цим:

int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));

Чотири варіанти, які ви написали, - це зручні методи. Використовувати їх слід лише тоді, коли вони зручніші. Це теж найкращий підхід. Таким чином, в API дуже зрозуміло, які члени потрібні, а які - ні. Якщо ви не хочете писати чотири способи, ви можете уточнити речі, називаючи свої параметри:

public int calculateSomething(String p1OrNull, BigDecimal p2OrNull)

Таким чином, зрозуміло, що нульові значення дозволені.

Ваше використання p1.orElse(null)ілюструє, наскільки багатослівний наш код отримує при використанні необов’язкового, що є частиною того, чому я уникаю цього. Необов’язково було написано для функціонального програмування. Потоки цього потребують. Ваші методи, ймовірно, ніколи не повинні повертати Факультативні, якщо не потрібно використовувати їх у функціональному програмуванні. Існують такі методи, як Optional.flatMap()метод, який вимагає посилання на функцію, яка повертає необов'язково. Ось його підпис:

public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)

Тому зазвичай це єдина вагома причина для написання методу, який повертає необов'язково. Але навіть там цього можна уникнути. Ви можете передати геттер, який не повертає Необов'язково до такого методу, як flatMap (), загорнувши його в інший метод, який перетворює функцію у потрібний тип. Метод обгортки виглядає приблизно так:

public static <T, U> Function<? super T, Optional<U>> optFun(Function<T, U> function) {
    return t -> Optional.ofNullable(function.apply(t));
}

Тож припустимо, у вас такий геттер: String getName()

Ви не можете передати його до flatMap так:

opt.flatMap(Widget::getName) // Won't work!

Але ви можете передати це так:

opt.flatMap(optFun(Widget::getName)) // Works great!

Поза функціонального програмування слід уникати додаткових варіантів.

Брайан Гец сказав це найкраще, коли сказав це:

Причина Необов’язкове додавання до 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;

1
Ну, це ОДНА з причин, що його додали до Java. Є багато інших. Заміна довгих ланцюжків вкладених операторів "if", які потрапляють у структуру даних з єдиною послідовністю ланцюгових викликів на Optional.map - це моя особиста улюбленість. Світ програмування функціональних мов має багато цікавих застосувань для факультативного, крім простої заміни нульових чеків, як це.
Деякий хлопець
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.