Pytanie Unikanie! = Puste instrukcje


używam object != null wiele do uniknięcia NullPointerException.

Czy istnieje dobra alternatywa dla tego?

Na przykład:

if (someobject != null) {
    someobject.doCalc();
}

Pozwala to uniknąć NullPointerException, gdy nie wiadomo, czy obiekt jest null albo nie.

Pamiętaj, że zaakceptowana odpowiedź może być nieaktualna, zobacz https://stackoverflow.com/a/2386013/12943 dla nowszego podejścia.


3553


pochodzenie


@Shervin Zachęcające wartości null powodują, że kod jest mniej zrozumiały i mniej niezawodny. - Tom Hawtin - tackline
Operatorzy Elvisa byli proponowane ale wygląda na to, że nie będzie Java 7. Szkoda,?. ?: i? [] to niesamowita oszczędność czasu. - Scott
Nie używanie wartości null jest lepsze niż większość innych propozycji tutaj. Zgłaszaj wyjątki, nie zwracaj ani nie zezwalaj na wartości zerowe. BTW - słowo kluczowe "assert" jest bezużyteczne, ponieważ jest domyślnie wyłączone. Użyj zawsze włączonego mechanizmu awarii - ianpojman
To jeden z powodów, dla których teraz używam Scala. W Scali wszystko nie jest null. Jeśli chcesz zezwolić na przekazanie lub zwrócenie "nic", musisz użyć opcji [T] zamiast tylko argumentu T als lub typu zwrotu. - Thekwasti
@thSoft Rzeczywiście, Scala jest niesamowita Option typ jest nękany przez niechęć tego języka do kontrolowania lub odrzucania null. Wspomniałem o tym na hackernews i otrzymałem poparcie i powiedziałem, że "nikt nie używa null w Scala". Zgadnij co, już znajduję nulls w napisanej przez współpracowników Scali. Tak, oni "robią to źle" i muszą być o tym wykształceni, ale faktem pozostaje, że system języka powinien chronić mnie przed tym i nie :( - Andres F.


Odpowiedzi:


To dla mnie brzmi jak dość powszechny problem, na który w pewnym momencie napotykają młodsi i średniozaawansowani deweloperzy: albo nie wiedzą albo nie ufają kontraktom, w których uczestniczą, i defensywnie kontrolują, czy nie są puste. Dodatkowo, pisząc własny kod, zazwyczaj polegają na zwracanych wartościach zerowych, aby wskazać coś, co wymaga od osoby dzwoniącej sprawdzenia wartości null.

Innymi słowy, istnieją dwa przypadki, w których pojawia się zerowe sprawdzanie:

  1. Gdzie null jest poprawną odpowiedzią pod względem kontraktu; i

  2. Gdzie nie jest poprawna odpowiedź.

(2) jest łatwe. Albo użyj assert oświadczenia (asercje) lub pozwolić na niepowodzenie (na przykład NullPointerException). Asercje to bardzo niedostatecznie wykorzystana funkcja Java, która została dodana w wersji 1.4. Składnia jest następująca:

assert <condition>

lub

assert <condition> : <object>

gdzie <condition> jest wyrażeniem boolowskim i <object> jest obiektem, którego toString() Wyniki metody zostaną uwzględnione w błędzie.

Na assert oświadczenie rzuca Error (AssertionError) jeśli warunek nie jest spełniony. Domyślnie Java ignoruje asercje. Możesz włączyć potwierdzenia, przekazując opcję -ea do JVM. Możesz włączać i wyłączać asercje dla poszczególnych klas i pakietów. Oznacza to, że możesz sprawdzać poprawność kodu z zapewnieniami podczas tworzenia i testowania oraz wyłączać je w środowisku produkcyjnym, chociaż moje testy wykazały, że nie ma wpływu na wydajność w przypadku asercji.

Niewykonanie asercji w tym przypadku jest OK, ponieważ kod po prostu zawiedzie, co stanie się, jeśli użyjesz asercji. Jedyna różnica polega na tym, że w przypadku twierdzeń może to nastąpić wcześniej, w bardziej znaczący sposób i ewentualnie z dodatkowymi informacjami, które mogą pomóc w ustaleniu, dlaczego tak się stało, jeśli nie oczekiwałeś tego.

(1) jest nieco trudniejsze. Jeśli nie masz kontroli nad kodem, do którego dzwonisz, utkniesz. Jeśli null jest poprawną odpowiedzią, musisz to sprawdzić.

Jeśli jednak kontrolujesz kod (i tak często się zdarza), to jest inna historia. Unikaj używania wartości zerowych w odpowiedzi. Dzięki metodom, które zwracają kolekcje, jest to proste: prawie zawsze zwracaj puste kolekcje (lub tablice) zamiast wartości zerowych.

W przypadku nie-kolekcji może być trudniej. Rozważmy to jako przykład: jeśli masz następujące interfejsy:

public interface Action {
  void doSomething();
}

public interface Parser {
  Action findAction(String userInput);
}

gdzie Parser pobiera surowe dane wejściowe od użytkownika i znajduje coś, co może zrobić, jeśli implementujesz coś w interfejsie wiersza poleceń. Teraz możesz spowodować, że kontrakt zwróci wartość null, jeśli nie zostanie podjęte odpowiednie działanie. To prowadzi do zerowej kontroli, o której mówisz.

Alternatywnym rozwiązaniem jest nigdy nie zwracać wartości null i zamiast tego używać Wzór zerowy obiektu:

public class MyParser implements Parser {
  private static Action DO_NOTHING = new Action() {
    public void doSomething() { /* do nothing */ }
  };

  public Action findAction(String userInput) {
    // ...
    if ( /* we can't find any actions */ ) {
      return DO_NOTHING;
    }
  }
}

Porównać:

Parser parser = ParserFactory.getParser();
if (parser == null) {
  // now what?
  // this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
  // do nothing
} else {
  action.doSomething();
}

do

ParserFactory.getParser().findAction(someInput).doSomething();

który jest znacznie lepszym projektem, ponieważ prowadzi do bardziej zwięzłego kodu.

To powiedziawszy, być może jest całkowicie właściwe, aby metoda findAction () wysyłała wyjątek znaczącym komunikatem o błędzie - szczególnie w tym przypadku, gdy polegasz na danych wprowadzanych przez użytkownika. Znacznie lepiej byłoby, gdyby metoda findAction wyrzuciła wyjątek, niż metodę wywołania, aby wysadzić w powietrze prosty wyjątek NullPointerException bez żadnego wyjaśnienia.

try {
    ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
    userConsole.err(anfe.getMessage());
}

Lub jeśli uważasz, że mechanizm try / catch jest zbyt brzydki, zamiast robić nic, domyślne działanie powinno przekazywać użytkownikowi informacje zwrotne.

public Action findAction(final String userInput) {
    /* Code to return requested Action if found */
    return new Action() {
        public void doSomething() {
            userConsole.err("Action not found: " + userInput);
        }
    }
}

2392



Nie zgadzam się z Twoimi stwierdzeniami za działanie DO_NOTHING. Jeśli metoda znajdowania akcji nie może znaleźć akcji, wówczas należy zwrócić wartość NULL. "Znalazłeś" działanie w kodzie, którego tak naprawdę nie znaleziono, co narusza zasadę metody, aby znaleźć użyteczne działanie. - MetroidFan2002
Zgadzam się, że wartość null jest nadużywana w Javie, szczególnie w przypadku list. Tak wiele apisów byłoby lepiej, gdyby zwrócili pustą listę / tablicę / kolekcję zamiast wartości zerowej. Wiele razy, null jest używany tam, gdzie zamiast tego powinien zostać zgłoszony wyjątek. Wyjątek powinien zostać zgłoszony, jeśli analizator składni nie może przeanalizować. - Laplie Anderson
Ostatni przykład to IIRC, wzór projektu Null Object. - Steven Evers
@Cshah (i MetroidFan2002). Prosto, umieść to w umowie, a następnie jasne jest, że nieodnaleziona zwrócona akcja nic nie da. Jeśli jest to ważna informacja dla osoby dzwoniącej, podaj sposób, aby odkryć, że była to akcja nie znaleziona (tj. Zapewnić metodę sprawdzania, czy wynik był obiektem DO_NOTHING). Alternatywnie, jeśli normalnie można znaleźć działanie, to nadal nie powinieneś zwracać wartości null, ale zamiast tego wyrzucać wyjątek specjalnie wskazujący ten warunek - to nadal daje lepszy kod. W razie potrzeby podaj osobną metodę zwracającą wartość boolowską, aby sprawdzić, czy istnieje działanie. - Kevin Brock
Zwięzły nie jest równoznaczny z kodem jakości. Przepraszam, tak myślisz. Twój kod ukrywa sytuacje, w których błąd byłby korzystny. - gshauger


Jeśli używasz (lub planujesz użyć) Java IDE, jak JetBrains IntelliJ IDEA, Eclipse lub Netbeans lub narzędzie takie jak findbugs, możesz użyć adnotacji, aby rozwiązać ten problem.

Zasadniczo, masz @Nullable i @NotNull.

Możesz użyć w metodzie i parametrach, takich jak to:

@NotNull public static String helloWorld() {
    return "Hello World";
}

lub

@Nullable public static String helloWorld() {
    return "Hello World";
}

Drugi przykład nie zostanie skompilowany (w IntelliJ IDEA).

Kiedy używasz pierwszego helloWorld() funkcja w innym kawałku kodu:

public static void main(String[] args)
{
    String result = helloWorld();
    if(result != null) {
        System.out.println(result);
    }
}

Teraz kompilator IntelliJ IDEA powie ci, że czek jest bezużyteczny, ponieważ helloWorld() funkcja nie wróci null, zawsze.

Korzystanie z parametru

void someMethod(@NotNull someParameter) { }

jeśli napiszesz coś takiego:

someMethod(null);

To się nie skompiluje.

Ostatni przykład użycia @Nullable

@Nullable iWantToDestroyEverything() { return null; }

Robiąc to

iWantToDestroyEverything().something();

I możesz być pewien, że tak się nie stanie. :)

To dobry sposób, aby kompilator mógł sprawdzić coś więcej niż zwykle i wzmocnić swoje kontrakty. Niestety nie jest obsługiwany przez wszystkie kompilatory.

W IntelliJ IDEA 10.5 i później dodali obsługę dla każdego innego @Nullable  @NotNull wdrożenia.

Zobacz wpis na blogu Bardziej elastyczne i konfigurowalne adnotacje @ Nullable / @ NotNull.


518



@NotNull, @Nullable oraz inne adnotacje o braku ważności są częścią JSR 305. Można ich również użyć do wykrywania potencjalnych problemów za pomocą narzędzi takich jak FindBugs. - Jacek S
Uważam to za dziwnie denerwujące, że @NotNull& @Nullable interfejsy na żywo w pakiecie com.sun.istack.internal. (Przypuszczam, że kojarzę com.sun z ostrzeżeniami o używaniu zastrzeżonego API). - Jonik
Przeniesienie kodu kończy się na jetbrainach. Dwukrotnie pomyślałem (kwadrat) przed przywiązaniem do poziomu idei. Jak powiedział Jacek S, są częścią JSR w dowolny sposób, który moim zdaniem był JSR303. - Java Ka Baby
Naprawdę nie sądzę, że używanie niestandardowego kompilatora jest realnym rozwiązaniem tego problemu. - Shivan Dragon
Dobra rzecz o adnotacjach, które @NotNull i @Nullable jest to, że ładnie degradują się, gdy kod źródłowy jest budowany przez system, który ich nie rozumie. W efekcie argument, że kod nie jest przenośny, może być nieważny - jeśli używasz systemu, który obsługuje i rozumie te adnotacje, masz dodatkową korzyść w postaci dokładniejszego sprawdzania błędów, w przeciwnym razie otrzymasz mniej, ale Twój kod powinien nadal dobrze, a jakość twojego uruchomionego programu jest TAKIEGO SAMEGO, ponieważ adnotacje te i tak nie zostały wymuszone w środowisku wykonawczym. Poza tym wszystkie kompilatory są niestandardowe ;-) - amn


Jeśli wartości null nie są dozwolone

Jeśli twoja metoda jest wywoływana zewnętrznie, zacznij od czegoś takiego:

public void method(Object object) {
  if (object == null) {
    throw new IllegalArgumentException("...");
  }

Następnie, w pozostałej części tej metody, będziesz to wiedział object nie ma wartości NULL.

Jeśli jest to metoda wewnętrzna (nie jest częścią API), po prostu udokumentuj, że nie może być wartością null, i to wszystko.

Przykład:

public String getFirst3Chars(String text) {
  return text.subString(0, 3);
}

Jeśli jednak twoja metoda po prostu przekazuje wartość, a następna metoda przekaże ją itd., Może to być problematyczne. W takim przypadku możesz sprawdzić argument tak jak powyżej.

Jeśli wartość null jest dozwolona

To naprawdę zależy. Jeśli stwierdzę, że często robię coś takiego:

if (object == null) {
  // something
} else {
  // something else
}

Więc rozgałęzam się i robię dwie zupełnie różne rzeczy. Nie ma brzydkiego fragmentu kodu, ponieważ naprawdę muszę zrobić dwie różne rzeczy w zależności od danych. Na przykład, czy powinienem pracować na wejściu, czy też powinienem obliczyć dobrą domyślną wartość?


Właściwie to rzadko używam idiomu "if (object != null && ...".

Może być łatwiej podać Ci przykłady, jeśli pokażesz przykłady miejsc, w których zwykle używasz idiomu.


282



Jaki jest cel wrzucania wyjątku IllegalArgumentException? Myślę, że wyjątek NullPointerException byłby wyraźniejszy, a także zostałby zgłoszony, jeśli sam nie wykonasz testu zerowego. Albo użyłbym twierdzenia, albo nic. - Axel
Jest mało prawdopodobne, że każda wartość inna niż zero jest akceptowalna. Możesz mieć IllegalArgumentException, OutOfRageException itp. Czasami ma to sens. Innym razem, gdy tworzysz wiele klas wyjątków, które nie dodają żadnej wartości, po prostu użyj IllegalArgumentException. Nie ma sensu mieć jednego wyjątku dla danych wejściowych o wartości null, a innego dla wszystkiego innego. - myplacedk
Tak, zgadzam się na zasadę fail-fast, ale w powyższym przykładzie wartość nie jest przekazywana, ale jest obiektem, na który zostanie wywołana metoda. A więc nie działa szybko, a dodanie zerowego czeku tylko po to, aby rzucić wyjątek, który i tak byłby wyrzucany w tym samym czasie i miejscu, nie ułatwiłoby debugowania. - Axel
Dziura bezpieczeństwa? JDK jest pełen takiego kodu. Jeśli nie chcesz, aby użytkownik widział ścieżki stosu, po prostu je wyłącz. Nikt nie sugerował, że zachowanie nie jest udokumentowane. MySQL jest napisany w C, gdzie dereferencja wskaźników null jest niezdefiniowanym zachowaniem, niczym jak wyrzucenie wyjątku. - fgb
throw new IllegalArgumentException("object==null") - Thorbjørn Ravn Andersen


Wow, prawie nie lubię dodawać innej odpowiedzi, gdy mamy 57 różnych sposobów, aby polecić NullObject pattern, ale myślę, że niektórzy ludzie zainteresowani tym pytaniem mogą chcieć wiedzieć, że na stole znajduje się propozycja dodania Java 7 "bezpieczna obsługa"- uproszczona składnia logiki, jeśli nie jest równa zerowej.

Przykład podany przez Alexa Millera wygląda następująco:

public String getPostcode(Person person) {  
  return person?.getAddress()?.getPostcode();  
}  

The ?. oznacza tylko odroczenie lewego identyfikatora, jeśli nie jest zerowy, w przeciwnym razie oceń pozostałą część wyrażenia jako null. Niektórzy ludzie, jak członek Java Posse Dick Wall i wyborców w Devoxx naprawdę uwielbiam tę propozycję, ale jest też opozycja, uzasadniająca to faktem, że faktycznie zachęci ona do częstszego korzystania z niej null jako wartość wartownika.


Aktualizacja: Na oficjalna propozycja dla operatora bezpiecznego zerowego w Java 7 został złożony w ramach Moneta projektu. Składnia jest trochę inna niż powyższy przykład, ale jest to to samo pojęcie.


Aktualizacja: Propozycja operatora bezpiecznego dla null nie pojawiła się w Monecie Projektu. Tak więc nie zobaczysz tej składni w Javie 7.


215



Myślę, że to jest złe. Powinien istnieć sposób na określenie, że dana zmienna jest ZAWSZE wartością inną niż null. - Thorbjørn Ravn Andersen
Aktualizacja: propozycja nie spowoduje utworzenia Java7. Widzieć blogs.sun.com/darcy/entry/project_coin_final_five . - Boris Terzic
Interesujący pomysł, ale wybór składni jest absurdem; Nie chcę bazy kodów pełnej znaków zapytania przypiętych do każdego złącza. - Rob
Ten operator istnieje w Groovy, więc ci, którzy chcą z niego korzystać, nadal mają to jako opcję. - Muhd
To najbardziej pomysłowy pomysł, jaki widziałem. Należy go dodać do każdego rozsądnego języka składni C. Wolę "przypinać znaki zapytania" wszędzie, niż przewijać ekrany linii lub unikać "klauzul strażniczych" przez cały dzień. - Victor


Jeśli niezdefiniowane wartości są niedozwolone:

Możesz skonfigurować IDE tak, aby ostrzegało Cię przed potencjalnym dereferencją o wartości zerowej. Na przykład. w Eclipse, patrz Preferencje> Java> Kompilator> Błędy / Ostrzeżenia / Analiza Null.

Jeśli niezdefiniowane wartości są dozwolone:

Jeśli chcesz zdefiniować nowy interfejs API, gdzie wartości niezdefiniowane mają sens, Użyj Wzór opcji (może być znajomy z języków funkcjonalnych). Ma następujące zalety:

  • W interfejsie API wyraźnie stwierdza się, czy dane wejściowe lub wyjściowe istnieją, czy też nie.
  • Kompilator zmusza do obsługi "niezdefiniowanej" sprawy.
  • Opcja to monada, więc nie ma potrzeby pełnego sprawdzania wartości null, wystarczy użyć mapy / foreach / getOrElse lub podobnego kombinatora, aby bezpiecznie użyć wartości (przykład).

Java 8 ma wbudowany Optional klasa (zalecane); w przypadku wcześniejszych wersji istnieją alternatywy biblioteki, na przykład Guava„s Optional lub FunctionalJava„s Option. Ale podobnie jak wiele wzorców w stylu funkcjonalnym, użycie opcji w Javie (nawet 8) powoduje powstanie całkiem sporego zestawu znaków, który można zredukować za pomocą mniej gadatliwego języka JVM, np. Scala lub Xtend.

Jeśli masz do czynienia z API, które może zwrócić wartości null, nie można wiele zrobić w Javie. Xtend i Groovy mają Operator Elvisa  ?: i null-safe dereference operator  ?., ale zwróć uwagę, że ta zwraca null w przypadku odwołania zerowego, więc po prostu "odrzuca" poprawną obsługę wartości null.


177



Rzeczywiście, wzór opcji jest niesamowity. Niektóre odpowiedniki Java istnieją. Guava zawiera ograniczoną wersję tego o nazwie Opcjonalnie, która pozostawia większość funkcjonalnych rzeczy. W Haskell ten wzorzec nazywa się Może. - Ben Hardy
Klasa opcjonalna będzie dostępna w Javie 8 - Pierre Henry
... i nie ma (jeszcze) mapy ani płaskiej mapy: download.java.net/jdk8/docs/api/java/util/Optional.html - thSoft
Opcjonalny wzór niczego nie rozwiązuje; zamiast jednego potencjalnie pustego obiektu, teraz masz dwa. - Boann
@Boann, jeśli będziesz go używać ostrożnie, rozwiążesz wszystkie problemy związane z NPE. Jeśli nie, to wydaje mi się, że istnieje problem "użytkowania". - Louis F.


Tylko w tej sytuacji -

Nie sprawdzanie, czy zmienna ma wartość null przed wywołaniem metody równości (ciąg znaków porównuje poniższy przykład):

if ( foo.equals("bar") ) {
 // ...
}

spowoduje wynik NullPointerException gdyby foo nie istnieje.

Możesz tego uniknąć, jeśli porównasz swoje Strings tak:

if ( "bar".equals(foo) ) {
 // ...
}

160



Zgadzam się - tylko w tej sytuacji. Nie mogę znieść programistów, którzy wzięli to na następny niepotrzebny poziom i napisali, że (null! = MyVar) ... wygląda mi na brzydkiego i nie służy żadnemu celowi! - Alex Worden
Jest to szczególny przykład, prawdopodobnie najczęściej wykorzystywany, ogólnej dobrej praktyki: jeśli ją znasz, zawsze rób to <object that you know that is not null>.equals(<object that might be null>);. Działa dla innych metod niż equals jeśli znasz umowę i te metody mogą obsłużyć null parametry. - Stef
To pierwszy przykład, jaki widziałem Warunki Yoda to ma sens - Erin Drummond
Wyrażenia NullPointerExceptions są generowane z konkretnego powodu. Są one generowane, ponieważ obiekt jest pusty, gdzie nie powinien być. Zadaniem programistów jest naprawienie tego, a nie ukrywanie problemu. - Oliver Watkins
Try-Catch-DoNothing ukrywa problem, jest to dobra praktyka, aby obejść brak cukru w ​​danym języku. - echox


Z Java 8 pochodzi nowy java.util.Optional klasa, która prawdopodobnie rozwiązuje część problemu. Można przynajmniej powiedzieć, że poprawia to czytelność kodu, a w przypadku publicznych interfejsów API sprawia, że ​​kontrakt API jest wyraźniejszy dla dewelopera klienta.

Działają tak:

Obiekt opcjonalny dla danego typu (Fruit) jest tworzony jako typ zwracany przez metodę. Może być pusty lub zawierać Fruit obiekt:

public static Optional<Fruit> find(String name, List<Fruit> fruits) {
   for (Fruit fruit : fruits) {
      if (fruit.getName().equals(name)) {
         return Optional.of(fruit);
      }
   }
   return Optional.empty();
}

Teraz spójrz na ten kod, w którym przeszukujemy listę Fruit (fruits) dla danej instancji Fruit:

Optional<Fruit> found = find("lemon", fruits);
if (found.isPresent()) {
   Fruit fruit = found.get();
   String name = fruit.getName();
}

Możesz użyć map() operator, aby wykonać obliczenia na - lub wyodrębnić wartość - opcjonalnego obiektu. orElse() pozwala podać rezerwę na brakujące wartości.

String nameOrNull = find("lemon", fruits)
    .map(f -> f.getName())
    .orElse("empty-name");

Oczywiście nadal konieczne jest sprawdzenie wartości pustej / pustej, ale przynajmniej deweloper jest świadomy, że wartość może być pusta, a ryzyko zapomnienia o kontroli jest ograniczone.

W API zbudowanym od zera za pomocą Optional za każdym razem, gdy zwracana wartość może być pusta, i zwracanie zwykłego obiektu tylko wtedy, gdy nie może być null (konwencja), kod klienta może porzucić kontrolę zerową dla wartości zwracanych przez proste obiekty ...

Oczywiście Optional może być również użyty jako argument metody, być może lepszym sposobem na wskazanie argumentów opcjonalnych niż 5 lub 10 metod przeciążania w niektórych przypadkach.

Optional oferuje inne dogodne metody, takie jak orElse które pozwalają na użycie wartości domyślnej, oraz ifPresent to działa wyrażeń lambda.

Zapraszam do lektury tego artykułu (moje główne źródło do napisania tej odpowiedzi), w którym NullPointerException (i ogólnie wskaźnik zerowy) problematyczne, a także (częściowe) rozwiązanie spowodowane przez Optional są dobrze wyjaśnione: Obiekty opcjonalne Java.


135



Guava Google ma opcjonalną implikację dla środowiska Java 6+. - Bradley Gottfried
Jego bardzo ważne jest, aby podkreślić, że używanie Opcjonalnego tylko z ifPresent () robi nie dodaje wiele wartości powyżej normalnego sprawdzania zerowego. Jego podstawową wartością jest to, że jest to monada, która może być używana w łańcuchach funkcji map / flapMap, która osiąga podobne wyniki, jak w przypadku innego operatora Elvisa w Groovy. Nawet bez tego użycia uważam, że bardzo przydatna jest również składnia orElse / orElseThrow. - Cornel Masson
Ten blog ma dobry wpis na Opcjonalne winterbe.com/posts/2015/03/15/avoid-null-checks-in-java - JohnC
Naprawdę nigdy nie zrozumiałem, dlaczego ludzie są tak zadowoleni z tego kodu dzone.com/articles/java-8-elvis-operator - Mykhaylo Adamovych
Dlaczego ludzie mają tendencję do robienia tego if(optional.isPresent()){ optional.get(); } zamiast optional.ifPresent(o -> { ...}) - Satyendra Kumar


W zależności od rodzaju obiektów, które sprawdzasz, możesz korzystać z niektórych klas w apache commons takich jak: apache, wspólny język i zbiory apache commons

Przykład:

String foo;
...
if( StringUtils.isBlank( foo ) ) {
   ///do something
}

lub (w zależności od tego, co musisz sprawdzić):

String foo;
...
if( StringUtils.isEmpty( foo ) ) {
   ///do something
}

Klasa StringUtils jest tylko jedną z wielu; istnieje sporo dobrych klas we wspólnocie, która wykonuje bezpieczną manipulację zerową.

Poniżej znajduje się przykład, w jaki sposób można używać zerowej vallidation w JAVA, gdy dołączasz bibliotekę apache (commons-lang-2.4.jar)

public DOCUMENT read(String xml, ValidationEventHandler validationEventHandler) {
    Validate.notNull(validationEventHandler,"ValidationHandler not Injected");
    return read(new StringReader(xml), true, validationEventHandler);
}

A jeśli używasz Spring, Spring ma tę samą funkcjonalność w swoim pakiecie, zobacz bibliotekę (wiosna-2.4.6.jar)

Przykład użycia tego statycznego classf od wiosny (org.springframework.util.Assert)

Assert.notNull(validationEventHandler,"ValidationHandler not Injected");

113



Możesz także użyć bardziej ogólnej wersji z Apache Commons, całkiem przydatnej na początku metod sprawdzania paramów, które znajduję. Validate.notNull (object, "object nie może być pusty"); commons.apache.org/lang/apidocs/org/apache/commons/lang/... - monojohnny
@monojohnny ma Validate use Assert statement into ?. Pytam, ponieważ Assert może być aktywowany / dezaktywowany na JVM i sugeruje, aby nie używać go w produkcji. - Kurapika
Nie sądzę - wierzę, że po prostu wyrzuca wyjątek RuntimeException, jeśli sprawdzanie poprawności nie powiedzie się - monojohnny


  • Jeśli uważasz, że obiekt nie powinien być pusty (lub jest to błąd), użyj assert.
  • Jeśli twoja metoda nie akceptuje parametrów null, powiedz to w javadoc i użyj assert.

Musisz sprawdzić obiekt! = Null tylko jeśli chcesz obsłużyć przypadek, w którym obiekt może być pusty ...

Pojawiła się propozycja dodania nowych adnotacji w Javie7, aby pomóc w parametrach null / notnull: http://tech.puredanger.com/java7/#jsr308


87



Nie, nie używaj asercji w kodzie produkcyjnym. - Blauhirn


Jestem fanem kodu "fail fast". Zadaj sobie pytanie - czy robisz coś użytecznego w przypadku, gdy parametr ma wartość zerową? Jeśli nie masz jasnej odpowiedzi na pytanie, co powinien zrobić twój kod w takim przypadku ... nie powinno nigdy być wartością null, a następnie zignorować ją i pozwolić na wygenerowanie wyjątku NullPointerException. Kod wywołujący będzie miał tyle samo wartości NPE, co wyjątek IllegalArgumentException, ale programiści będą łatwiej debugować i rozumieć, co poszło nie tak, gdy zostanie zgłoszony NPE, a nie kod, który próbuje wykonać inne niespodziewane zdarzenia. logika - co ostatecznie powoduje awarię aplikacji.


80



lepiej używać asercji, np. Contract.notNull (abc, "abc musi być non-null, czy nie udało się załadować podczas xyz?"); - jest to bardziej kompaktowy sposób niż wykonywanie instrukcji if (abc! = null) {throw new RuntimeException ...} - ianpojman


Czasami masz metody, które działają na swoich parametrach, które definiują operację symetryczną:

a.f(b); <-> b.f(a);

Jeśli wiesz, że b nigdy nie może być wartością null, możesz po prostu ją zamienić. Jest to najbardziej przydatne dla równych: Zamiast foo.equals("bar"); lepiej "bar".equals(foo);.


69



Ale musisz założyć equals (może być dowolną metodą) obsłuży poprawnie wartość null. Naprawdę to wszystko polega na przekazywaniu odpowiedzialności komuś innemu (lub innej metodzie). - Supericy
@Supericy Zasadniczo tak, ale equals (lub jakakolwiek metoda) musi sprawdzić null tak czy inaczej. Albo wyraź jednoznacznie, że tak nie jest. - Angelo Fuchs