Використання за бажанням


271

Використовуючи Java 8 зараз протягом понад 6 місяців, я дуже задоволений новими змінами API. Один із напрямків, в які я все ще не впевнений, - це коли використовувати Optional. Я, здається, розмахую між бажанням використовувати його скрізь, де щось може бути null, і ніде зовсім.

Здається, існує багато ситуацій, коли я міг би ним скористатися, і я ніколи не впевнений, чи додасть це користь (читабельність / нульова безпека) чи просто спричинить додаткові витрати.

Отож, у мене є кілька прикладів, і мене цікавлять думки громади про те, чи Optionalкорисно це.

1 - Як тип повернення публічного методу, коли метод може повернутись null:

public Optional<Foo> findFoo(String id);

2 - Як параметр методу, коли парам може бути null:

public Foo doSomething(String id, Optional<Bar> barOptional);

3 - Як необов'язковий член квасолі:

public class Book {

  private List<Pages> pages;
  private Optional<Index> index;

}

4 - В Collections:

Взагалі я не думаю:

List<Optional<Foo>>

додає що завгодно - тим більше, що можна використовувати filter()для видалення nullзначень тощо, але чи є корисні користі для Optionalколекцій?

Якись випадки я пропустив?


2
Я вважаю корисним один випадок, наприклад, якщо у вас є карта заміни. Наприклад Map<Character, String>. Якщо немає ніякої заміни я можу використовувати це: Optional.ofNullable(map.get(c)).orElse(String.valueOf(c)). Також зауважте, що необов'язково було вкрадено у Гуави, і він має набагато приємніший синтаксис:Optional.fromNullable(map.get(c)).or(String.valueOf(c));
fge

3
Крім того, в колекціях, ну, є колекції, які не дозволяють нульових значень! Необов’язково вкладається тут. І ви можете .filter(Optional::absent)"нульові значення" вийти
fge

2
@fge Чесно кажучи, я вважаю, що концепція Факультативу насправді випливає з ПП.
VH-NZZ

2
@fge не так виражено краще getOrDefault()?
Джим Гаррісон

Відповіді:


206

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

Це найбільш відповідає випадку використання №1 у питанні про ОП. Хоча відсутність значення є більш точним формулюванням, ніж null, оскільки щось подібне IntStream.findFirstніколи не може повернути null.

У випадку використання №2 , передаючи необов'язковий аргумент методу, це може бути спрацьоване, але це досить незграбно. Припустимо, у вас є метод, який приймає рядок, а потім необов'язковий другий рядок. Прийняття Optionalяк другого аргументу призведе до такого коду:

foo("bar", Optional.of("baz"));
foo("bar", Optional.empty());

Навіть прийняття нуля приємніше:

foo("bar", "baz");
foo("bar", null);

Напевно, найкраще мати перевантажений метод, який приймає аргумент одного рядка та забезпечує другий за замовчуванням:

foo("bar", "baz");
foo("bar");

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

Використання справ №3 та №4 , що мають Optionalполе класу або структуру даних, вважається неправильним використанням API. По-перше, це суперечить основній меті дизайну, Optionalяк зазначено вгорі. По-друге, це не додає ніякої цінності.

Існує три способи впоратися з відсутністю значення в Optional: надавати значення замінника, викликати функцію для надання значення замінника або викинути виняток. Якщо ви зберігаєте в полі, ви зробите це під час ініціалізації чи призначення. Якщо ви додаєте значення в список, як згадувалося в ОП, у вас є додатковий вибір - просто не додавати значення, тим самим "вирівнювати" відсутні значення.

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


46
Я не згоден з №3. Це може бути корисно мати поле Optionalяк поле, коли щось потрібно робити чи не робити за наявності чи відсутності значення.
glglgl

15
Я не бачу, чому робити if(foo == null)всередині було б краще, ніж просто зберігати поле як optional. І я не бачу, чому явно викликати getOptionalFoo()внутрішнє дзвінок краще, ніж просто зберігати поле як Optional. Крім того, якщо одне поле може бути, nullа одного не може бути null, чому б не повідомити про це компілятору, зробивши їх Optionalчи ні Optional.
mogronalol

27
@StuartMarks, це одна з речей, яка мене просто бентежить, коли я чую це від усіх Optional<>експертів: "не зберігай Optional<>у полі". Я справді намагаюся зрозуміти суть цієї рекомендації. Розглянемо дерево DOM, де у вузла може бути батько чи ні. Здається, у випадку використання воно Node.getParent()повернеться Optional<Node>. Я дійсно очікується, nullщо кожен раз зберігатимуть та обговорювати результат? Чому? Що мені купує ця додаткова неефективність, окрім того, щоб зробити мій код некрасивим?
Гаррет Вілсон

7
@GarretWilson З іншого боку, припустимо, у вас є Optional<Node> getParent() { return Optional.ofNullable(parent); }. Це виглядає дорого, бо виділяє Optionalщоразу! Але якщо абонент розпаковує його негайно, об'єкт надзвичайно короткочасний і його ніколи не просувають поза простором. Це, можливо, навіть буде усунене аналізом втечі JIT. Відповідь в нижньому рядку - "це залежить", як завжди, але використання Optionalв полях потенційно розширює використання пам'яті та уповільнює проходження структури даних. І, нарешті, я думаю, що це захаращує код, але це питання смаку.
Стюарт Маркс

6
@GarretWilson Отже, ти написав блог для цього? Мене би зацікавило це :)
akhil_mittal

78

Я запізнююсь на гру, але для того, що вона варта, я хочу додати свої 2 центи. Вони суперечать дизайнерській метіOptional , яку добре узагальнено у відповідь Стюарта Маркса , але я все одно переконаний у їх обґрунтованості (очевидно).

Використовуйте необов’язково скрізь

В загальному

Я написав цілу публікацію в блозі про використання,Optional але в основному зводиться до цього:

  • спроектуйте свої заняття, щоб уникнути факультативності, де це можливо
  • у всіх інших випадках за замовчуванням слід використовувати Optionalзамістьnull
  • можливо зробити винятки для:
    • локальні змінні
    • повернути значення та аргументи до приватних методів
    • продуктивні критичні блоки коду (не здогадуйтесь, використовуйте профілер)

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

Зауважте, що це майже ніколи не дозволить Optionals в колекціях, що майже так само погано, як і nulls. Просто не робіть цього. ;)

Щодо ваших питань

  1. Так.
  2. Якщо перевантаження не є варіантом, так.
  3. Якщо інші підходи (підкласифікація, декорування, ...) не є варіантом, так.
  4. Будь ласка, ні!

Переваги

Це зменшує присутність nulls у вашій кодовій базі, хоча це не усуває їх. Але це навіть не головний пункт. Є й інші важливі переваги:

Уточнює наміри

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

Знімає невизначеність

Без Optionalсенсу nullподії незрозуміло. Це може бути юридичне представлення стану (див. Map.get) Або помилка впровадження, як-от відсутня або невдала ініціалізація.

Це різко змінюється при постійному використанні Optional. Тут вже поява nullозначує наявність помилки. (Тому що якби значення було дозволено відсутнє, було Optionalб використано.) Це значно спрощує налагодження виключення з нульовим вказівником, оскільки на питання про значення цього nullзначення вже відповіли.

Більше нульових перевірок

Тепер, коли вже нічого не може бути null, це можна виконувати скрізь. З анотаціями, твердженнями або простими чеками, вам ніколи не доведеться думати про те, чи може цей аргумент чи той тип повернення бути недійсним. Це не може!

Недоліки

Звичайно, срібної кулі немає ...

Продуктивність

Встановлення значень (особливо примітивів) у додатковий екземпляр може погіршити продуктивність. У вузьких петлях це може стати помітним або навіть гіршим.

Зауважте, що компілятор, можливо, зміг би обійти додаткову посилання на короткочасне життя Optionals. У Java 10 типи значень можуть додатково зменшити або зняти штраф.

Серіалізація

Optionalне є серіалізаційним, але вирішення не надто складне.

Інваріантність

Через інваріантність загальних типів на Java, певні операції стають громіздкими, коли фактичний тип значення висувається в аргумент загального типу. Тут наведено приклад (див. «Параметричний поліморфізм») .


Ще одним недоліком (або обмеженням) є те, що ви не можете сортувати необов’язкові (xxx) екземпляри, хоча Oracle чітко наклав це обмеження навмисно. Я скептично ставлюсь до розумності надання цих класів у тих місцях, де їх слід використовувати лише в конкретних умовах, і припускаю, що розробник зробить правильно. Вирішення однієї проблеми може спричинити іншу. Можливо, повинні бути попередження компілятора, щоб допомогти розробнику при використанні необов'язкових (xxx) класів "небажаними" способами (наприклад, як параметри методу, у колекціях, у конструкторах тощо), якщо це дійсно не призначене для використання?
skomisa

Близько 4, необов'язкові в колекціях: насправді іноді корисно зберігати необов’язкові елементи в Lists. Це той випадок, коли важливо, щоб певний елемент був розташований у певному індексі, але елемент може бути присутнім чи ні. Це чітко повідомляється List<Optional<T>>типом. Якщо, з іншого боку, важливо лише, які об’єкти, які є членами якоїсь колекції, то немає сенсу.
Лій

3
Я думаю, що випадок використання 2 все ще дуже сумнівний. Перехід Optionalу метод може бути null. То що ви здобули? Тепер у вас є два чеки. Дивіться stackoverflow.com/a/31923042/650176
David V

2
@DavidV подивіться на перелік переваг, які я дав - всі вони стосуються і цього випадку. Крім того, якщо ви все продовжуєте Optionalдіяти (що має бути так, якщо ви готові передати це як аргументи), nullце ніколи не має юридичної цінності. Тому викликати метод із явним параметром null, очевидно, є помилкою.
Миколай

28

Особисто я вважаю за краще використовувати інструмент перевірки коду IntelliJ для використання @NotNullта @Nullableперевірки, оскільки це значною мірою час компіляції (може мати кілька перевірок виконання) Це має менші накладні витрати з точки зору читабельності коду та продуктивності виконання. Це не настільки суворо, як використання Необов’язкового, однак ця відсутність суворості повинна бути підкріплена гідними одиничними тестами.

public @Nullable Foo findFoo(@NotNull String id);

public @NotNull Foo doSomething(@NotNull String id, @Nullable Bar barOptional);

public class Book {

  private List<Pages> pages;
  private @Nullable Index index;

}

List<@Nullable Foo> list = ..

Це працює з Java 5 і не потрібно загортати та розгортати значення. (або створити обгорткові об'єкти)


7
Гм, це анотації IDEA? Я віддаю перевагу @Nonnullособисто JSR 305 - працює з FindBugs;)
fge

@fge У цьому плані бракує стандартів, але я вважаю, що інструменти, як правило, налаштовані, і вам не доведеться закінчувати це@Nonnull @NotNull etc
Пітер Лорі

4
Так це правда; IDEA (13.x) дає три різні варіанти ... Мех, я завжди користуюся JSR 305 anywa
fge

3
Я знаю, що це старе, але дискусія про анотації та інструменти заслуговує на посилання на stackoverflow.com/questions/35892063/… - яке btw спеціально стосується випадку Java 8.
Стефан Геррман

25

Я думаю, що Guava необов’язково та їх вікі-сторінка це дуже добре:

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

Це особливо актуально, коли ви повертаєте значення, які можуть бути або не бути "присутніми". Ви (та інші) набагато більше шансів забути, що other.method (a, b) може повернути нульове значення, ніж ви, ймовірно, забудете, що a може бути нульовим, коли ви реалізуєте other.method. Повернення за бажанням викликає неможливість забувати цей випадок, оскільки вони повинні самі розгортати об'єкт, щоб зібрати свій код. - (Джерело: Guava Wiki - Використання та уникнення нуля - Який сенс? )

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

Беручи приклад 2 , я думаю, що набагато більш явний код написати:

if(soundcard.isPresent()){
  System.out.println(soundcard.get());
}

ніж

if(soundcard != null){
  System.out.println(soundcard);
}

Для мене Optionalкраще фіксує той факт, що звукової карти немає.

Мої 2 ¢ про ваші бали:

  1. public Optional<Foo> findFoo(String id);- Я не впевнений у цьому. Можливо, я б поверну, Result<Foo>який може бути порожнім або містити Foo. Це схоже поняття, але насправді не є Optional.
  2. public Foo doSomething(String id, Optional<Bar> barOptional);- Я вважаю за краще @Nullable і перевірку набуття помилок, як у відповіді Пітера Лодрі - див. Також цю дискусію .
  3. Приклад вашої книги - Я не впевнений, чи не використовував би я Опціонально всередині, це може залежати від складності. Для "API" книги я використовував Optional<Index> getIndex()би явно вказати, що книга може не мати індексу.
  4. Я б не використовував його у колекціях, швидше не дозволяючи нульових значень у колекціях

Взагалі, я б намагався мінімізувати проходження навколо nulls. (Колись спалено ...) Я думаю, що варто знайти відповідні абстракції і вказати колегам-програмістам, що насправді являє певне повернене значення.


15
Ви б написали soundcard.ifPresent(System.out::println). Виклик isPresentсемантично такий же, як перевірка null.
кращий олівер

Проблема для мене полягає в тому, що речі з необов’язковими типами все ще можуть бути недійсними. Тож, щоб насправді бути повністю безпечним, потрібно робити щось подібне if(soundcard != null && soundcard.isPresent()). Хоча я сподіваюся, що робити api, який повертає необов’язково, а також може повернути нуль - це те, що я сподіваюся, що ніхто ніколи не робить.
Simon Baumgardt-Wellander

"Це змушує вас активно думати про відсутній випадок, якщо ви хочете, щоб ваша програма взагалі збиралася, оскільки вам потрібно активно розгортати Необов’язковий і вирішувати цей випадок." Я не дуже впевнений, як це змушує це робити, хоча я багато не працюю на Java. Чи можете ви пояснити, що робить Java, щоб змусити її розгортати та перевіряти!
розчавити

15

З підручника Oracle :

Призначення Факультативного - не замінювати кожну нульову посилання у вашій кодовій базі, а допомогти розробити кращі API, в яких - лише прочитавши підпис методу - користувачі можуть сказати, чи варто очікувати необов'язкове значення. Крім того, необов'язково змушує вас активно розгортати Факультативу, щоб боротися з відсутністю значення; як результат, ви захищаєте свій код від випадкових винятків нульових покажчиків.


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

@ycomp Ви можете знайти досить багато інформації про ті випадки , в цьому або що питання. Відповіді на ці запитання говорять набагато більше, ніж те, про що вони задавали, та охоплюють інші випадки. Для отримання додаткової інформації перегляньте більше або задайте власне запитання, тому що, напевно, тут не будете приділяти багато уваги. ; )
ctomek

8

1 - як тип повернення відкритого методу, коли метод може повернути нуль:

Ось хороша стаття, яка демонструє корисність використання №1. Там цей код

...
if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        Country country = address.getCountry();
        if (country != null) {
            String isocode = country.getIsocode();
            isocode = isocode.toUpperCase();
        }
    }
}
...

трансформується до цього

String result = Optional.ofNullable(user)
  .flatMap(User::getAddress)
  .flatMap(Address::getCountry)
  .map(Country::getIsocode)
  .orElse("default");

за допомогою необов’язкового як зворотного значення відповідних методів отримання .


2

Ось цікаве використання (я вважаю) для ... Тестів.

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

Тому я будую речі для затвердження і використовую atert для їх перевірки, як це:

public final class NodeDescriptor<V>
{
    private final Optional<String> label;
    private final List<NodeDescriptor<V>> children;

    private NodeDescriptor(final Builder<V> builder)
    {
        label = Optional.fromNullable(builder.label);
        final ImmutableList.Builder<NodeDescriptor<V>> listBuilder
            = ImmutableList.builder();
        for (final Builder<V> element: builder.children)
            listBuilder.add(element.build());
        children = listBuilder.build();
    }

    public static <E> Builder<E> newBuilder()
    {
        return new Builder<E>();
    }

    public void verify(@Nonnull final Node<V> node)
    {
        final NodeAssert<V> nodeAssert = new NodeAssert<V>(node);
        nodeAssert.hasLabel(label);
    }

    public static final class Builder<V>
    {
        private String label;
        private final List<Builder<V>> children = Lists.newArrayList();

        private Builder()
        {
        }

        public Builder<V> withLabel(@Nonnull final String label)
        {
            this.label = Preconditions.checkNotNull(label);
            return this;
        }

        public Builder<V> withChildNode(@Nonnull final Builder<V> child)
        {
            Preconditions.checkNotNull(child);
            children.add(child);
            return this;
        }

        public NodeDescriptor<V> build()
        {
            return new NodeDescriptor<V>(this);
        }
    }
}

У класі NodeAssert я роблю це:

public final class NodeAssert<V>
    extends AbstractAssert<NodeAssert<V>, Node<V>>
{
    NodeAssert(final Node<V> actual)
    {
        super(Preconditions.checkNotNull(actual), NodeAssert.class);
    }

    private NodeAssert<V> hasLabel(final String label)
    {
        final String thisLabel = actual.getLabel();
        assertThat(thisLabel).overridingErrorMessage(
            "node's label is null! I didn't expect it to be"
        ).isNotNull();
        assertThat(thisLabel).overridingErrorMessage(
            "node's label is not what was expected!\n"
            + "Expected: '%s'\nActual  : '%s'\n", label, thisLabel
        ).isEqualTo(label);
        return this;
    }

    NodeAssert<V> hasLabel(@Nonnull final Optional<String> label)
    {
        return label.isPresent() ? hasLabel(label.get()) : this;
    }
}

Що означає, що ствердження справді спрацьовує лише в тому випадку, якщо я хочу перевірити етикетку!


2

Optionalклас дозволяє уникати використання nullта надання кращої альтернативи:

  • Це спонукає розробника робити перевірки на наявність, щоб уникнути невдач NullPointerException.

  • API стає краще задокументованим, оскільки можна побачити, де очікувати значення, які можуть бути відсутніми.

Optionalнадає зручний API для подальшої роботи з об’єктом isPresent():; get(); orElse(); orElseGet(); orElseThrow(); map(); filter(); flatmap().

Крім того, багато фреймворків активно використовують цей тип даних і повертають його зі свого API.


2

У Java просто не використовуйте їх, якщо ви не пристрасті до функціонального програмування.

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

Вони мають сенс для повернення значень, але вони пропонують клас клієнта продовжувати розтягувати ланцюг побудови поведінки.

FP і ланцюги мають мало місця в такій необхідній мові, як java, тому що це дуже важко налагоджувати, а не просто читати. Коли ви переходите до рядка, ви не можете знати стану та наміру програми; вам доведеться вступити, щоб розібратися в цьому (в код, який часто не є вашим, і багато кадрів стека є глибокими, незважаючи на ступінчасті фільтри), і вам доведеться додати багато точок переривання вниз, щоб переконатися, що він може зупинитися в доданому вами коді / лямбда, замість того, щоб просто ходити тривіальними лініями if / else / call.

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


1

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

Основна ідея: Відсутність значення не означає, що воно потенційно є доступним у майбутньому. Це різниця між findById (-1) і findById (67).

Основна інформація Факультативів для абонента полягає в тому, що він може не розраховувати на вказане значення, але воно може бути доступним через деякий час. Можливо, воно зникне знову і повернеться пізніше ще раз. Це як перемикач включення / вимкнення. У вас є "опція" вмикати або вимикати світло. Але у вас немає можливості, якщо у вас немає світла для включення.

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


0

Здається , Optionalце тільки корисно , якщо тип T в Вибрані моделі примітивний тип , як int, long, charі т.д. Для «реальних» класів, це не має сенсу для мене , як ви можете використовувати nullзначення в будь-якому випадку.

Я думаю, це було взято звідси (або з іншої подібної мовної концепції).

Nullable<T>

У C # це Nullable<T>було введено давно, щоб обернути типи значень.


2
Це Optionalфактично
зріст Гуави

2
@fge Добре, але коли це було в C # (2005, MS.NET 2.0), Guava не було, я думаю. І ... хто знає, звідки це взяв C #.
peter.petrov

3
@fge "Необов'язковий Ripoff з Guava" - це кумедний спосіб, оскільки хлопці з Guava брали участь у дискусіях, надавали свій досвід і загалом виступали за це java.util.Optional.
Стюарт Маркс

6
@fge Без сумніву, API API Java сильно вплинули на Guava. Я приймаю питання з "ripoff", який звучить як крадіжка. Хлопці з Guava внесли багато цінних ідей в Java 8
Стюарт Маркс

6
Ви пропускаєте суть. Необов’язково використовуватись замість повернення нуля. Це безпечніше, ніж потенційно викидати NullPointerException. Дивіться: oracle.com/technetwork/articles/java/…
Кілізо

0

Має аналогічну семантику незмінного екземпляр шаблону проектування ітератора :Optional

  • він може або не може посилатися на об'єкт (як задано isPresent())
  • його можна відкинути (використовувати get()), якщо він посилається на об'єкт
  • але він не може бути переведений на наступне положення в послідовності (у нього немає next()методу).

Тому розгляньте можливість повернення або передачі Optionalв контекстах, де ви, можливо, раніше розглядали можливість використання Java Iterator.


-1

Java SE 8 представляє новий клас під назвою java.util.Options,

Ви можете створити порожній необов’язковий або необов’язковий з нульовим значенням.

Optional<String> emptyOptional = Optional.empty(); 

Ось необов’язково з ненульовим значенням:

String valueString = new String("TEST");
Optional<String> optinalValueString = Optional.of(valueString );

Зроби щось, якщо значення є

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

String nullString = null;
if (nullString != null) {
    System.out.println(nullString);
}

Ви можете використовувати метод ifPresent () таким чином:

Optional<String> optinalString= null;
optinalString.ifPresent(System.out::println);

package optinalTest;

import java.util.Optional;

public class OptionalTest {
    public Optional<String> getOptionalNullString() {
        return null;
//      return Optional.of("TESt");
    }

    public static void main(String[] args) {

        OptionalTest optionalTest = new OptionalTest();

        Optional<Optional<String>> optionalNullString = Optional.ofNullable(optionalTest.getOptionalNullString());

        if (optionalNullString.isPresent()) {
            System.out.println(optionalNullString.get());
        }
    }
}

ця копія пасти мала на меті придбати дешеву репутацію, але не пов’язана з питаннями ОП
stinger
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.