Какой смысл в факультативном классе Гуавы

Я недавно читал об этом и видел людей, использующих этот класс, но в большинстве случаев, используя null работал бы так же хорошо - если бы не более интуитивно. Может кто-то привести конкретный пример, где Optional достигнет чего-то, что null не мог или намного чище? Единственное, о чем я могу думать, это использовать его с Maps которые не принимают null ключи, но даже это можно сделать с помощью бокового "отображения" значения null. Может ли кто-нибудь предоставить мне более убедительный аргумент? Спасибо.

4 ответа

Решение

Член команды гуавы здесь.

Вероятно, самый большой недостаток null в том, что не очевидно, что это должно означать в любом данном контексте: у него нет иллюстративного имени. Не всегда очевидно, что null означает "нет значения для этого параметра" - черт возьми, в качестве возвращаемого значения иногда это означает "ошибка", или даже "успех" (!!), или просто "правильный ответ - ничто". Optional это часто понятие, которое вы на самом деле имеете в виду, когда делаете переменную, допускающую значение nullable, но не всегда Если это не так, мы рекомендуем вам написать свой собственный класс, похожий на Optional но с другой схемой именования, чтобы понять, что вы на самом деле имеете в виду.

Но я бы сказал, самое большое преимущество Optional не в удобочитаемости: преимущество в его идиотостойкости. Это заставляет вас активно думать об отсутствующем случае, если вы хотите, чтобы ваша программа вообще компилировалась, поскольку вы должны активно разворачивать Optional и решить этот случай. Null позволяет легко забыть о вещах, и хотя FindBugs помогает, я не думаю, что это решает проблему почти так же хорошо. Это особенно актуально, когда вы возвращаете значения, которые могут присутствовать или не присутствовать. Вы (и другие), скорее всего, забудете это other.method(a, b) может вернуть null значение, чем вы, вероятно, забудете, что a может быть null когда вы реализуете other.method, возврате Optional вызывающие абоненты не могут забыть этот случай, поскольку им приходится самим разворачивать объект.

По этим причинам мы рекомендуем вам использовать Optional в качестве типа возврата для ваших методов, но не обязательно в аргументах вашего метода.

(Между прочим, это полностью извлечено из обсуждения здесь.)

Это действительно выглядит как Maybe Узор монад от Хаскелла.

Вы должны прочитать следующее, Wikipedia Monad (функциональное программирование):

И прочитайте " Из необязательного в монаду с гуавой" в блоге Kerflyn, где обсуждается необязательный из гуавы, используемый в качестве монады:


Изменить: В Java8 есть встроенный дополнительный, который имеет монадические операторы, такие как flatMap, Это был спорный вопрос, но, наконец, был реализован.

См. http://www.nurkiewicz.com/2013/08/optional-in-java-8-cheat-sheet.html

public Optional<String> tryFindSimilar(String s)  //...

Optional<Optional<String>> bad = opt.map(this::tryFindSimilar);
Optional<String> similar =       opt.flatMap(this::tryFindSimilar);

flatMap Оператор необходим, чтобы разрешить монадические операции, и позволяет легко объединять вызовы, которые все возвращают необязательные результаты.

Подумайте об этом, если вы использовали map оператор 5 раз вы бы в конечном итоге Optional<Optional<Optional<Optional<Optional<String>>>>> при использовании flatMap даст вам Optional<String>

Начиная с Java8 я бы предпочел не использовать Guava's Optional, который является менее мощным.

Одна из веских причин его использования заключается в том, что он делает ваши нули очень значимыми. Вместо того, чтобы возвращать нуль, который может означать много вещей (например, ошибка, или сбой, или пустой, и т. Д.), Вы можете поставить "имя" в нуль. Посмотрите на этот пример:

Давайте определим базовый POJO:

class PersonDetails {

String person;
String comments;

public PersonDetails(String person, String comments) {
    this.person = person;
    this.comments = comments;
}

public String getPerson() {
    return person;
}


public String getComments() {
    return comments;
}

}

Теперь давайте воспользуемся этим простым POJO:

public Optional<PersonDetails> getPersonDetailstWithOptional () {

  PersonDetails details = null; /*details of the person are empty but to the caller this is meaningless,
  lets make the return value more meaningful*/


    if (details == null) {
      //return an absent here, caller can check for absent to signify details are not present
        return Optional.absent();
    } else {
      //else return the details wrapped in a guava 'optional'
        return Optional.of(details);   
    }
}

Теперь давайте избегать использования null и делать наши проверки с помощью Optional, так что это имеет смысл

public void checkUsingOptional () {

    Optional<PersonDetails> details = getPersonDetailstWithOptional();

    /*below condition checks if persons details are present (notice we dont check if person details are null,
    we use something more meaningful. Guava optional forces this with the implementation)*/
    if (details.isPresent()) {

      PersonDetails details = details.get();

        // proceed with further processing
        logger.info(details);

    } else {
        // do nothing
        logger.info("object was null"); 
    }

    assertFalse(details.isPresent());
}

таким образом, в конце концов, это способ сделать нули значимыми и меньше двусмысленности.

Наиболее важным преимуществом Optional является то, что он добавляет больше деталей в контракт между исполнителем и вызывающей стороной функции. По этой причине полезно как для параметров, так и для типа возвращаемого значения.

Если вы делаете соглашение, чтобы всегда иметь Optional для возможных нулевых объектов вы добавляете больше пояснений к случаям, таким как:

  1. Optional<Integer> maxPrime(Optional<Integer> from, Optional<Integer> to)

    Контракт здесь четко указывает, что есть вероятность того, что результат не будет возвращен, но также показывает, что он будет работать с from а также to как отсутствующий.

  2. Optional<Integer> maxPrime(Optional<Integer> from, Integer to)

    В контракте указывается, что значение from является необязательным, поэтому отсутствующее значение может иметь особое значение, например, начинаться с 2. Я могу ожидать, что нулевое значение для to Параметр выдаст исключение.

Таким образом, хорошая часть использования Optional заключается в том, что контракт стал описательным (аналогично @NotNull аннотации), но также формально, так как вы должны написать код .get() справиться с Optional,

Другие вопросы по тегам