Łapanie NullPointerException
jest naprawdę problematyczne, ponieważ może się zdarzyć prawie wszędzie. Bardzo łatwo jest go złapać przez błąd, złapać go przez przypadek i kontynuować tak, jakby wszystko było normalne, ukrywając w ten sposób prawdziwy problem. Trudno sobie z tym poradzić, więc najlepiej całkowicie tego unikać. (Na przykład pomyśl o automatycznym rozpakowywaniu wartości null Integer
).
Proponuję Optional
zamiast tego użyć klasy. Jest to często najlepsze podejście, gdy chcesz pracować z wartościami, które są obecne lub nieobecne.
Używając tego, możesz napisać swój kod w ten sposób:
public Optional<Integer> m(Ws wsObject) {
return Optional.ofNullable(wsObject.getFoo()) // Here you get Optional.empty() if the Foo is null
.map(f -> f.getBar()) // Here you transform the optional or get empty if the Bar is null
.map(b -> b.getBaz())
.map(b -> b.getInt());
// Add this if you want to return null instead of an empty optional if any is null
// .orElse(null);
// Or this if you want to throw an exception instead
// .orElseThrow(SomeApplicationException::new);
}
Dlaczego opcjonalne?
Używanie Optional
s zamiastnull
dla wartości, które mogą być nieobecne, sprawia, że fakt ten jest bardzo widoczny i jasny dla czytelników, a system typów zapewni, że przypadkowo o tym nie zapomnisz.
Otrzymasz również dostęp do metod wygodniejszej pracy z takimi wartościami, takich jak map
i orElse
.
Czy nieobecność jest ważna czy błąd?
Ale zastanów się również, czy prawidłowy wynik dla metod pośrednich zwraca wartość null, czy też jest to oznaka błędu. Jeśli zawsze jest to błąd, prawdopodobnie lepiej jest zgłosić wyjątek niż zwrócić specjalną wartość lub aby same metody pośrednie zgłosiły wyjątek.
Może więcej opcji?
Jeśli z drugiej strony nieobecne wartości z metod pośrednich są prawidłowe, być może możesz przełączyć się na Optional
je również s?
Następnie możesz ich użyć w ten sposób:
public Optional<Integer> mo(Ws wsObject) {
return wsObject.getFoo()
.flatMap(f -> f.getBar())
.flatMap(b -> b.getBaz())
.flatMap(b -> b.getInt());
}
Dlaczego nie opcjonalne?
Jedynym powodem, dla którego mogę wymyślić, aby go nie używać, Optional
jest to, że jest to w naprawdę krytycznej dla wydajności części kodu i jeśli obciążenie związane ze zbieraniem elementów bezużytecznych okazuje się problemem. Dzieje się tak, ponieważ kilka Optional
obiektów jest przydzielanych za każdym razem, gdy kod jest wykonywany, a maszyna wirtualna może nie być w stanie ich zoptymalizować. W takim przypadku oryginalne testy if mogą być lepsze.
null
kontrolom, ponieważwsObject.getFoo().getBar().getBaz().getInt()
jest to już zapach kodu. Przeczytaj, czym jest „Prawo Demeter” i wolisz odpowiednio zmienić kod. Wtedy problem znull
czekami również zniknie. I pomyśl o użyciuOptional
.