JavaRush /Blog Java /Random-PL /Przerwa kawowa #161. Jak obsługiwać wartość Null w Javie ...

Przerwa kawowa #161. Jak obsługiwać wartość Null w Javie przy użyciu Opcjonalnie

Opublikowano w grupie Random-PL
Źródło: Medium Ten artykuł pomoże Ci lepiej zrozumieć cel Opcjonalny podczas pracy z kodem Java. Przerwa kawowa #161.  Jak obsługiwać wartość Null w Javie przy użyciu opcjonalnego - 1Kiedy po raz pierwszy zaczynałem pracować z kodem Java, często doradzano mi użycie opcji Opcjonalne. Ale wtedy nie bardzo rozumiałem, dlaczego użycie Opcjonalnego jest lepsze niż wdrożenie obsługi wartości null. W tym artykule chcę się z Wami podzielić, dlaczego uważam, że wszyscy powinniśmy częściej używać opcji Opcjonalnych i jak uniknąć nadmiernej opcjonalnie optymalizacji kodu, co jest szkodliwe dla jakości kodu.

Co jest opcjonalne?

Parametr Opcjonalny służy do przenoszenia obiektów i umożliwia obsługę odwołań o wartości null przez różne interfejsy API. Spójrzmy na fragment kodu:
Coffee coffee = new Coffee();
Integer quantity = coffee.getSugar().getQuantity();
Mamy instancję Coffee , w której pobieramy trochę cukru z instancji obiektu Sugar . Jeśli założymy, że w konstruktorze Coffee nigdy nie została ustawiona wartość ilości , to funkcja Coffee.getSugar().getQuantity() zwróci wyjątek NullPointerException . Oczywiście zawsze możemy użyć starych, dobrych kontroli zerowych , aby rozwiązać problem.
Coffee coffee = new Coffee();
Integer quantity = 0;
if (coffee.getSugar() != null) {
  quantity = coffee.getSugar().getQuantity();
}
Teraz wszystko wydaje się być w porządku. Ale pisząc kod Java, lepiej unikać stosowania kontroli zerowych . Zobaczmy, jak można to zrobić za pomocą Opcjonalnie.

Jak utworzyć Opcjonalne

Istnieją trzy sposoby tworzenia obiektów opcjonalnych:
  • of(T value) — utworzenie opcjonalnego obiektu o wartości innej niż null. Należy pamiętać, że użycie of() w odniesieniu do obiektu o wartości null spowoduje wygenerowanie wyjątku NullPointerException .

  • ofNullable(wartość T) - tworzy wartość opcjonalną dla obiektu, który może mieć wartość null.

  • pusty() — Tworzy opcjonalną instancję, która reprezentuje odwołanie do null .

// пример использования Optional.of(T Value)
String name = "foo";
Optional<String> stringExample = Optional.of(name)
// пример использования Optional.ofNullable(T Value)
Integer age = null;
Optional<Integer> integerExample= Optional.ofNullable(age)
// пример использования Optional.empty()
Optional<Object> emptyExample = Optional.empty();
Masz więc obiekt opcjonalny. Przyjrzyjmy się teraz dwóm głównym metodom Opcjonalnym:
  • isPresent() — ta metoda informuje, czy obiekt opcjonalny zawiera wartość różną od null.

  • get() — Pobiera wartość Opcjonalną z bieżącą wartością. Należy pamiętać, że wywołanie metody get() na pustym obiekcie Option spowoduje zwrócenie wyjątku NullPointerException .

Pamiętaj, że jeśli podczas pracy z opcją Option użyjesz tylko funkcji get() i isPresent() , wiele stracisz! Aby to zrozumieć, przepiszemy teraz powyższy przykład za pomocą Opcjonalne.

Ulepszanie sprawdzania wartości zerowej za pomocą opcji

Jak zatem możemy ulepszyć powyższy kod? Dzięki Opcjonalnym możemy zrozumieć obecność obiektu za pomocą isPresent() i pobrać go za pomocą get() . Zacznijmy od spakowania wyniku kawy.getSugar() za pomocą opcji Opcjonalne i użycia metody isPresent() . Pomoże nam to ustalić, czy funkcja getSugar() zwraca wartość null.
Coffee coffee = new Coffee();
Optional<String> sugar = Optional.ofNullable(coffee.getSugar());
int quantity = 0;
if (sugar.isPresent()) {
  Sugar sugar = sugar.get();
  int quantity = sugar.getQuantity();
}
Patrząc na ten przykład, pakowanie wyniku funkcji Coffee.getSugar() do Opcjonalnej nie wydaje się dodawać żadnej wartości, a raczej dodaje kłopotów. Wynik możemy poprawić korzystając z moich ulubionych funkcji z klasy Opcjonalne:
  • map(Function<? super T,? Extends U> mapper) - Mapuje wartość zawartą w Opcjonalne na podaną funkcję. Jeśli parametr Opcjonalny jest pusty, map() zwróci Opcjonalną.empty() .

  • orElse(T other) to „specjalna” wersja metody get() . Może uzyskać wartość zawartą w Opcjonalne. Jednakże w przypadku pustej Opcjonalnej zwróci to wartość przekazaną do metody orElse() .

Metoda zwróci wartość zawartą w instancji Opcjonalne. Jeśli jednak parametr Opcjonalny jest pusty, co oznacza, że ​​nie zawiera wartości, funkcja orElse() zwróci wartość przekazaną do sygnatury metody, która jest nazywana wartością domyślną.
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
    .map(it -> it.getQuantity())
    .orElse(0);
To jest naprawdę fajne – przynajmniej tak mi się wydaje. Jeśli teraz w przypadku pustej wartości nie chcemy zwracać wartości domyślnej, to musimy zgłosić jakiś wyjątek. orElseThrow(Dostawca<? rozszerza X> wyjątekDostawca) zwraca wartość zawartą w parametrach opcjonalnych lub zgłasza wyjątek, jeśli opcjonalny jest pusty.
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
  .map(it -> it.getQuantity())
  .orElseThrow(IllegalArgumentException::new);
Jak widać, Opcjonalne zapewnia kilka korzyści:
  • streszczenia kontroli zerowych
  • udostępnia interfejs API do obsługi obiektów null
  • pozwala na podejście deklaratywne do wyrażenia tego, co zostało osiągnięte

Jak stać się skutecznym dzięki Opcjonalnym

W mojej pracy używam Opcjonalny jako typu zwracanego, gdy metoda może zwrócić stan „brak wyniku”. Zwykle używam go przy definiowaniu typów zwracanych metod.
Optional<Coffee> findByName(String name) {
   ...
}
Czasami nie jest to konieczne. Na przykład, jeśli mam metodę zwracającą wartość int , taką jak getQuantity() w klasie Sugar , wówczas metoda może zwrócić 0 , jeśli wynikiem jest null , co oznacza „brak ilości”. Wiedząc o tym, możemy pomyśleć, że parametr Sugar w klasie Coffee można przedstawić jako opcjonalny. Na pierwszy rzut oka wydaje się to dobrym pomysłem, ponieważ teoretycznie cukier nie musi być obecny w kawie. Jednak w tym miejscu chciałbym się poruszyć, kiedy nie używać Opcjonalnego. Powinniśmy unikać używania Opcjonalnego w następujących scenariuszach:
  • Jako typy parametrów dla POJO , takich jak DTO . Opcji nie można serializować, więc użycie ich w POJO powoduje, że obiektu nie można serializować.

  • Jako argument metody. Jeśli argumentem metody może być null , to z perspektywy czystego kodu przekazanie wartości null jest nadal lepsze niż przekazanie Opcjonalne. Ponadto można utworzyć przeciążone metody, aby abstrakcyjnie obsłużyć brak argumentu metody o wartości null.

  • Aby reprezentować brakujący obiekt kolekcji. Kolekcje mogą być puste, więc pusta kolekcja , taka jak pusta Set lub List , musi zostać użyta do reprezentowania kolekcji bez wartości.

Wniosek

Opcja opcjonalna stała się potężnym dodatkiem do biblioteki Java. Zapewnia sposób obsługi obiektów, które mogą nie istnieć. Dlatego należy mieć to na uwadze przy opracowywaniu metod, aby nie wpaść w pułapkę nadużyć. Tak, możesz napisać świetny kod, który implementuje sprawdzanie wartości null i obsługę wartości null, ale społeczność Java woli używać opcji Opcjonalne. Skutecznie komunikuje, jak radzić sobie z brakującymi wartościami, jest znacznie łatwiejszy do odczytania niż niechlujne kontrole zerowe i na dłuższą metę skutkuje mniejszą liczbą błędów w kodzie.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION