package ar.com.javacuriosities.streams; import java.util.Optional; /* * La clase Optional fue agregada en Java 1.8 y además de ser usada en de Streams API, puede * ser muy provechoso para evitar problemas como NPE (NullPointerException) */ public class Lesson06Optional { public static void main(String[] args) { System.out.println("Common Java Code"); Student student = createStudent(); // En muchos casos como estos debemos validar que la referencia // retornada no sea Null if (student != null) { System.out.println("Student: " + student.getName()); // Luego si queremos obtener la dirección también debemos chequear // por Null Address address = student.getAddress(); if (address != null) { System.out.println("Address: " + address); // Luego si queremos obtener el teléfono asociado a esa dirección Telephone telephone = address.getTelephone(); if (telephone != null) { System.out.println("Telephone: " + telephone); } } } System.out.println("Java Code with Optional"); /* * Una forma de mejorar el código de arriba es indicando que nuestra función puede * retornar Null de forma explícita, esto lo podemos hacer por medio de Optional lo * cual es un contenedor a una referencia y podemos utilizar sus métodos auxiliares */ Optional<Student> optionalStudent = createOptionalStudent(); // Podemos chequear si hay una referencia por medio del método ifPresent() optionalStudent.ifPresent(s -> System.out.println("Student: " + s.getName())); // Aquí estamos verificando una condición sobre nuestra referencia, este código es similar a "if (student != null && student.getAge() > 18)" optionalStudent.filter(s -> s.getAge() > 18).ifPresent(s -> System.out.println("Age: " + s.getAge())); Optional<Student> optionalStudentWithAddress = createOptionalStudentWithAddress(); /* * Usando la utilidad de map podemos encadenar operaciones y eliminar la redundancia al validar el código contra Null, este código es similar a: * if (student != null) { * if (student.getAddress() != null) { * if(student.getAddress().getTelephone() != null) { * System.out.println("Telephone: " + student.getAddress().getTelephone()); * } * } * } */ optionalStudentWithAddress.map(Student::getAddress).map(Address::getTelephone).ifPresent(t -> System.out.println("Telephone: " + t)); Optional<Student> nullStudent = createNullStudent(); // Podemos usar el método orElse para recibir la referencia contenida en el Optional o una creada en el momento en caso de que fuera Null System.out.println("Default Student: " + nullStudent.orElse(new Student("Pedro Picapiedra", 99))); } private static Student createStudent() { return new Student("Cosme Fulanito", 99); } private static Optional<Student> createNullStudent() { return Optional.ofNullable(null); } private static Optional<Student> createOptionalStudent() { // Para crear un Optional podemos usar los métodos of o ofNullable dependiendo si sabemos si la referencia puede ser Null o no return Optional.of(new Student("Cosme Fulanito", 99)); } private static Optional<Student> createOptionalStudentWithAddress() { return Optional.of(new Student("Cosme Fulanito", 99, new Address("Street Leader", 1234, new Telephone("12345678", "Home")))); } private static final class Student { private String name; private int age; private Address address; public Student(String name, int age) { super(); this.name = name; this.age = age; } public Student(String name, int age, Address address) { super(); this.name = name; this.age = age; this.address = address; } public String getName() { return name; } public int getAge() { return age; } public Address getAddress() { return address; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + ", address=" + address + "]"; } } private static final class Address { private String street; private int number; private Telephone telephone; public Address(String street, int number, Telephone telephone) { super(); this.street = street; this.number = number; this.telephone = telephone; } public Telephone getTelephone() { return telephone; } @Override public String toString() { return "Address [street=" + street + ", number=" + number + ", telephone=" + telephone + "]"; } } private static final class Telephone { private String number; private String type; public Telephone(String number, String type) { super(); this.number = number; this.type = type; } @Override public String toString() { return "Telephone [number=" + number + ", type=" + type + "]"; } } }