Jaki jest sens fakultatywnej klasy Guava

Ostatnio czytałem o tym i widziałem ludzi używających tej klasy, ale w prawie wszystkich przypadkach użycie null zadziałałoby równie dobrze-jeśli nie bardziej intuicyjnie. Czy ktoś może podać konkretny przykład, gdzie Optional osiągnąłby coś, czego null nie mógł lub w znacznie czystszy sposób? Jedyne, co przychodzi mi do głowy, to użycie go z Maps, które nie akceptują kluczy null, ale nawet to można zrobić z bocznym "mapowaniem" wartości null. Czy ktos moze mi dostarczyc bardziej przekonujaca kłótnia? Dziękuję.

Author: Trying, 2012-03-05

4 answers

Tu członek drużyny Guava.

Prawdopodobnie największą wadą null jest to, że nie jest oczywiste, co powinno oznaczać w danym kontekście: nie ma ilustracyjnej nazwy. Nie zawsze jest oczywiste, że null oznacza "brak wartości dla tego parametru" -- heck, jako wartość zwracana, czasami oznacza "błąd", a nawet" sukces" (!!), lub po prostu "prawidłowa odpowiedź jest niczym". {[2] } jest często pojęciem, które masz na myśli, gdy zmieniasz zmienną nullable, ale nie zawsze. Jeśli tak nie jest, zalecamy napisanie własnej klasy, podobnej do Optional, ale z innym schematem nazewnictwa, aby wyjaśnić, co masz na myśli.

Ale powiedziałbym, że największą zaletą Optional nie jest czytelność: zaletą jest jej idiotoodporność. Zmusza cię to do aktywnego myślenia o nieobecnym przypadku, jeśli chcesz, aby twój program w ogóle się skompilował, ponieważ musisz aktywnie rozpakować Optional i zająć się tą sprawą. Null sprawia, że łatwo jest po prostu zapomnieć o rzeczach i chociaż FindBugs pomaga, nie sądzę, aby rozwiązywał ten problem prawie tak dobrze. Jest to szczególnie istotne, gdy zwracasz wartości, które mogą, ale nie muszą być "obecne."Ty (i inni) najprawdopodobniej zapomnisz, że {[6] } może zwrócić wartość null, niż prawdopodobnie zapomnisz, że a może być null, gdy wdrażasz other.method. Zwrócenie Optional sprawia, że dzwoniący nie mogą zapomnieć o tej sprawie, ponieważ sami muszą rozpakować obiekt.

Z tych powodów, my zaleca się użycie Optional jako typu zwrotnego dla metod, ale niekoniecznie w argumentach metody.

(tak przy okazji, jest to całkowicie wykreślone z dyskusji tutaj .)

 155
Author: Louis Wasserman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-07 16:05:26

To naprawdę wygląda jak Maybe Wzór Monad z Haskell.

Powinieneś przeczytać: Wikipedia Monad (Programowanie funkcyjne):

Na blogu Kerflyn, który omawia fakultatywne użycie guawy jako monady, można przeczytać od opcjonalnego do monady z Guawą.]}

Edit: W Java8 jest wbudowana opcja, która ma monadyczne operatory, takie jak flatMap. Jest to temat kontrowersyjny, ale wreszcie został wdrożony.

Zobacz 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);

Operator flatMap jest niezbędny do umożliwienia operacji monadycznych i pozwala na łatwe łączenie wywołań, które zwracają opcjonalne wyniki.

Pomyśl o tym, jeśli użyjesz operatora map 5 razy, skończysz z Optional<Optional<Optional<Optional<Optional<String>>>>>, podczas gdy użycie flatMap da ci Optional<String>

Ponieważ Java8 wolałbym nie używać opcji Guava, która jest mniej potężny.

 9
Author: Sebastien Lorber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-06 00:19:58

Dobrym powodem, aby go używać jest to, że sprawia, że Twoje nulle są bardzo znaczące. Zamiast zwracać wartość null, która może oznaczać wiele rzeczy (np. Błąd, niepowodzenie, pusta itp.), Możesz umieścić' nazwę ' Do null. Spójrz na ten przykład:

Zdefiniujmy podstawowe 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;
}

}

Teraz skorzystajmy z tego prostego 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);   
    }
}

Teraz unikamy używania null i wykonujemy nasze kontrole z opcjonalnym więc jego znaczenie

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());
}

Tak więc w końcu jest to sposób, aby null znaczące i mniej niejednoznaczne.

 6
Author: j2emanue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-06 00:52:41

Najważniejszą zaletą opcjonalnego jest to, że dodaje więcej szczegółów do Umowy między wykonawcą a wywołującym funkcji. Z tego powodu jest użyteczny zarówno dla parametrów, jak i typu return.

Jeśli sprawisz, że konwencja będzie zawsze mieć Optional dla możliwych obiektów null, dodasz więcej wyjaśnień do przypadków takich jak:

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

    Umowa tutaj jasno określa, że istnieje szansa, że wynik nie zostanie zwrócony, ale pokazuje również, że będzie działał z from i to jako nieobecne.

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

    Umowa określa, że od jest opcjonalne, więc nieobecna wartość może mieć specjalne znaczenie, takie jak początek od 2. Mogę się spodziewać, że wartość null dla parametru to rzuci wyjątek.

Więc dobrą częścią używania opcjonalnego jest to, że umowa stała się zarówno opisowa (podobnie z @NotNull adnotacją), ale także formalna, ponieważ musisz napisać kod .get(), aby poradzić sobie z Optional.

 4
Author: raisercostin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55