ABONAMENTE VIDEO REDACȚIA
RO
EN
×
▼ LISTĂ EDIȚII ▼
Numărul 32
Abonament PDF

Java 8 Optional nu este doar pentru înlocuirea unei valori null

Peter Lawrey
CEO @ Higher Frequency Trading Ltd
PROGRAMARE

În Java 8 poți returna un Optional în loc de return null așa cum ai putea să faci în Java 7. Aceasta ar putea sau nu să fie o mare diferenţă în funcţie de frecvenţa cu care tinzi să uiţi să verifici null sau să foloseşti analiza de cod static pentru a verifica referinţele de null. Există totuși un caz care te constrânge mai mult. Acesta constă în a trata Optional ca pe un Stream cu valori 0 sau 1.

Caz simplu de utilizare Optional

Pe vremea lui Java 7, am fi scris ceva de genul:

String text = something();
if (text != null) {

Observaţie: Oracle Java 7 va avea sfârșitul actualizărilor publice în aprilie 2015. Cu Optional, vei putea scrie în schimb:

Optional text = something();
if (text.isPresent()) {
    String text2 = text.get();

Totuşi, dacă eşti paranoic, ai putea scrie:

Optional text = something();
if (text != null && text.isPresent()) {
    String text2 = text.get();

Dacă ai multe erori NullPointerException în proiectul tău, Optional s-ar putea să te ajute, dar altfel nu va fi de prea mult ajutor.

Un exemplu mai complex

Haideţi să luăm în considerare acest exemplu:

static String getFirstSecondThird(Nested nested) {
 try {
 return ((Contained2) nested.first.second).get(0).third;
 } catch (NullPointerException | 
   ClassCastException | 
     IndexOutOfBoundsException ignored) {
          return null;
    }
}

Este destul de complicat. În loc să vânezi excepţii, poţi concepe o listă lungă de verificare a condiţiilor, dar este dificil să vezi ceea ce încerci să faci. Optional îți permite să gestionezi toate condiţiile de eroare posibile, fără a prinde excepţii sau a avea if/else imbricate.

static Optional getFirstSecondThird(Optional nested) {
 return nested // could be non-present
   .map(x -> x.first) // could be null
   .map(x -> x.second) // could be null
    // could be another type
    .map(x -> x instanceof Contained2 ? 

      (Contained2) x : null)
      .map(x -> x.list) // could be null
      .filter(x -> !x.isEmpty()) // could be empty
      .map(x -> x.get(0)) // could be null
      .map(x -> x.third); // could be null.
}

Ceea ce obţinem este o serie de reprezentări şi filtre care progresează doar dacă valoarea nu este null şi prezentă. Dacă vreo valoare este nul sau un filtru nu este adevărat, întregul rezultat nu va fi disponibil.

Concluzie

Folosirea lui Optional poate fi o modalitate puternică de a dirija o structură complexă de date într-un mod sigur. Scopul lambda este de a reduce codul boilerplate (care nu necesită multă modificare), iar în acest caz, evită toate verificările sau erorile ce pot apărea.

Adiţional

Pentru interesul vostru, iată clasele pe care le-am utilizat în exemplul anterior:

static class Nested {
    Contained first;
}

static class Contained {
    IContained2 second;
}

interface IContained2 {
}

static class Contained2 implements IContained2 {
List list;
}

static class Data {
    String third;
}

Sponsori

  • comply advantage
  • ntt data
  • 3PillarGlobal
  • Betfair
  • Telenav
  • Accenture
  • Siemens
  • Bosch
  • FlowTraders
  • MHP
  • Connatix
  • UIPatj
  • MetroSystems
  • Globant
  • Colors in projects