Neste guia você irá aprender como funciona o Optional, um novo recurso adicionado no Java 8 e saberá como usá-lo.
Introdução
A classe Optional foi adicionada na versão do 8 no pacote java.util. Esta classe foi introduzida para verificar se um valor está presente, evitando o famoso erro de NullPointerException.
Um objeto Optional é um container que pode ou não conter um valor.
Métodos mais usados
A classe Optional possui vários métodos, entre eles temos o isPresent() e get().
-
isPresent(): Verifica se o objetoOptionalpossui algum valor que seja diferente de vazio ounull. Retornatruese tiver algum valor, caso contrário retornafalse. -
get(): Recupera o valor de um objetoOptional.
Semelhante ao
isPresent()o métodoisEmpty()retornatruese estiver vazio, caso contrário, retornarátrue. Este método foi adicionado no Java 11.
package to.dev;
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional<String> stringOptional = Optional.of("Hello");
if (stringOptional.isPresent()) {
System.out.println(stringOptional.get()); // Hello
}
}
}
Para criar um Optional é preciso usar o método Optional.of(T value), este método retorna um Optional<T> do mesmo tipo do argumento fornecido em of(T value).
Ex. Optional<Long> longOptional = Optional.of(1L);
Optional.of(T value) e Optional.ofNullable(T value)
Só use of(T value) quando o argumento fornecido NUNCA será null. Caso contrário, será lançado um NullPointerException. Para evitar esse erro use ofNullable(T value)
public class OptionalExample {
public static void main(String[] args) {
Optional<String> stringOptional = Optional.ofNullable(null);
if (stringOptional.isPresent()) {
System.out.println(stringOptional.get());
}
}
}
Criando um Optional vazio
Para criar um Optional vazio use Optional.empty(). Ex. Optional<String> stringOptional = Optional.empty();
Optional com valores default - orElse(T other)
Caso um Optional esteja vazio e você queira retorna um valor padão basta usar o método orElse(T other).
package to.dev;
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional<Long> longOptional = Optional.ofNullable(null);
System.out.println(longOptional.orElse(99L)); // 99
}
}
Optional com valores default - orElseGet(Supplier<? extends T> supplier)
Esta alternativa recebe um Supplier como argumento, permitindo que você execute alguma operação.
Supplier: É uma interface funcional que não recebe argumentos, mas sempre retorna um valor.
package to.dev;
import java.time.LocalDate;
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional<Long> longOptional = Optional.ofNullable(null);
System.out.println(longOptional.orElseGet(() -> { // 29
int i = LocalDate.now().getDayOfMonth();
return (long) i;
}));
}
}
orElse(T other) vs orElseGet(Supplier<? extends T> supplier)
orElse(T other) retorna o valor dentro do container Optional se estiver presente, caso contrário, irá retornar o valor fornecido no argumento do método. orElseGet(Supplier<? extends T> supplier): retorna o valor dentro do container Optional, caso contrário, irá invocar o Supplier e retornará o resultado da invocação.
Filtrando um Optional
Para filtrar algum valor de Optional use o método filter(Predicate<? super T> predicate).
Predicate: É uma interface funcional que recebe um valor e sempre retorna um valor booleano.
package to.dev;
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional<Long> longOptional = Optional.ofNullable(30L);
Optional<Long> longFilter = longOptional.filter(v -> v > 18); // true
if (longOptional.isPresent()) {
System.out.println(longFilter.get()); // 30
}
}
}
Modificando o valor de um Optional com map(Function<? super T, ? extends U> mapper)
O método map() serve para modificar um valor dentro de um container Optional. Para isso é passado uma Function com argumento.
Function: É uma interface funcional que recebe um valor como argumento e retorna um valor que pode igual ou diferente do argumento passado.
package to.dev;
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional<String> longOptional = Optional.ofNullable("Hello");
Optional<String> longMap = longOptional.map(v -> {
if (v.contains("Hello")) {
return "Hello World";
} else {
return "Hello";
}
});
System.out.println(longMap.get()); // Hello World
}
}
Recebendo um Optional de outro Optional com flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)
O flatMap(Function<? super T, ? extends Optional<? extends U>> mapper) é usado quando você recebe um objeto Optional de um container Optional, Optional<Optional<Long>> longOptional = Optional.of(Optional.empty());.
package to.dev;
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional<String> stringOptional = Optional.of("Hello World");
Optional<Optional<String>> optionalStringOptional = Optional.of(stringOptional);
System.out.println(optionalStringOptional);
Optional<String> output = optionalStringOptional.flatMap(value -> value.map(String::toLowerCase));
System.out.println(output);
}
}
Executando uma lógica se o Optional estiver presente
Caso queira executar alguma operação se um valor estiver presente, uma alternativa é usar o método ifPresent(Consumer<? super T> consumer).
Consumer: É uma interface funcional que recebe argumentos, mas não retorna nenhum valor.
package to.dev;
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional<String> longOptional = Optional.ofNullable("Hello");
Optional<String> longMap = longOptional.map(v -> {
if (v.contains("Hello")) {
return "Hello World";
} else {
return "Hello";
}
});
longMap.ifPresent(v -> System.out.println(v)); // Hello World
}
}
Tratando exceções com orElseThrow(Supplier<? extends X> exceptionSupplier)
O método orElseThrow(Supplier<? extends X> exceptionSupplier) retorna o valor caso ele esteja presente, caso contrário, ele irá lançar um exceção fornecida pelo desenvolvedor.
Este método só está disponível no Java 10.
package to.dev;
import java.util.Optional;
class EmptyException extends Exception {
public EmptyException() {
super("Not found value");
}
}
public class OptionalExample {
public static void main(String[] args) throws EmptyException {
Optional<String> stringOptional = Optional.ofNullable(null);
System.out.println(stringOptional.orElseThrow()); // throws -> NoSuchElementException: No value present
System.out.println(stringOptional.orElseThrow(EmptyException::new)); // throws -> EmptyException: Not found value
}
}
Referência: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Optional.html
Top comments (0)