Java8 | Optional

Hasan Kadir Demircan
3 min readOct 7, 2021

--

As you know, most backend developers encounter NullPointerException. To solve this, we often set up a null check structure.
With Optional class, there is no need for this. This class has various utility methods to facilitate code to handle values as ‘available’ or ‘not available’ instead of checking null values.

How Can We Create an Optional

Optional<String> emptyOptional = Optional.empty(); // create empty optional

Optional<String> opt1 = Optional.of("value");
System.out.println(opt1); // Optional[value]
System.out.println(opt1.get()); // value
System.out.println(emptyOptional); // Optional.empty
  • The class java.util.Optional is a holder for a value that can be null. There are numerous methods in classes in java.util.stream package that returns Optional values

How Can We Handle NullPointerException

Optional<String> nullStr = Optional.of(null); //java.lang.NullPointerException
For Handle NullPointer
nullStr.ifPresent(System.out::println); // nothing writes
  • If some fields can be null, we should use Optional and we can control these fields with ifPresent().
  • ifPresent() method means if the field is null, it will escape the field.
  • we can also use Optional.ofNullable instead of Optional.of(), if we used Optional.ofNullable, we wouldn’t have to use ifPresent()
  • For example;
Optional<String> nullable = Optional.ofNullable(null);
System.out.println(nullable); // Optional.empty

Another example;

Optional<String> string = Optional.of("  abracadabra  ");

string.map(String::trim)
.ifPresent(System.out::println); //abracadabra
  • We can also consider Optional as a stream that can have zero elements or one element. So we can apply methods such as map(), filter(), and flatMap()

What should we do if we want to return another object or value if the value is empty?

  • Basically we can use orElse() or orElseThrow() methods,
Optional<String> string = Optional.ofNullable(null); //Optional.empty

System.out.println(string.map(String::length).orElse(-1)); // -1
System.out.println(string.map(String::length)
.orElseThrow(MyServiceException::new));
// returns MyServiceException
  • This code prints -1 because the variable string is an Optional variable that holds null, therefore, the orElse() method executes and returns.
  • In addition, we can use the orElse() and orElseThrow() method not only for null but also for data that do not comply with the rules we have determined.
  • So, we don’t have to use this flow,
if(number == null) {
return -1;
}

What is the difference between orElse(), orElseGet() and orElseThrow?

  • orElse() -> public T orElse(T other)
  • orElseGet() -> public T orElseGet(Supplier<? extends T> other)
    orElseGet takes supplier and returns T.
  • orElseThrow() ->
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

if we want to look in a sample;

Optional<Double> opt = Optional.empty();

System.out.println(opt.orElse(Double.NaN));
System.out.println(opt.orElseGet(Math::random));
System.out.println(opt.orElseThrow(IllegalStateException::new));

Optional Chaining

If we have a code that is a little bit complexity like below,

private static void threeDigit(Optional<Integer> optional) {
if (optional.isPresent()) {
Integer num = optional.get();
String string = "" + num;
if (string.length() == 3)
System.out.println(string);
}
}

it works but this code-block can be shorter and readable with functional programming like below,

private static void threeDigitV2(Optional<Integer> optional){
optional.map(n -> "" + n)
.filter(s -> s.length() == 3)
.ifPresent(System.out::println);
}

Primitive Versions of Optional<T>

We can use both Stream<Double> and Optional<Double> types,

public static void selectHighestTemperature(Stream<Double> temperatures) {
Optional<Double> max = temperatures.max(Double::compareTo);
max.ifPresent(System.out::println);
}

If we are working with primitive types, this code can be rewritten as;

public static void selectHighestTemperature(DoubleStream temperatures){
OptionalDouble max = temperatures.max();
max.ifPresent(System.out::println);
}

Github : Optional

--

--

Hasan Kadir Demircan
Hasan Kadir Demircan

No responses yet