How to properly unwrap an optional in Java?

Tags: , ,

I am learning the basics of Java and I am exploring Optionals and abstract classes so I came across the following issue,

I have this code

import java.util.Optional;

public abstract class Animal {
    abstract void makeSound();
    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();
        Horse horse = new Horse();
        Animal[] animals = {dog, cat, horse};
        for (Animal animal : animals) {
            Optional<Dog> _dog = animal instanceof Dog ? Optional.of((Dog) animal) : null;
            Optional<Cat> _cat = animal instanceof Cat ? Optional.of((Cat) animal) : null;
            Optional<Horse> _horse = animal instanceof Horse ? Optional.of((Horse) animal) : null;
            if (_dog.isPresent()) {
                System.out.println("it is a Dog");
            } else {
                System.out.println("it is NOT a Dog");

class Horse extends Animal {
    String speed = "Fast";
    void makeSound() {

class Dog extends Animal {
    String color = "Brown";
    void makeSound() {

class Cat extends Animal {
    Integer lives = 9;
    void makeSound() {

I was expecting to see the prints on the console “It is a Dog” followed by 2 “It is not a Dog” Since I’m using the method .isPresent() on optionals,

But I got 1 print and then a NullPointerException:

That’s what I got printed:

it is a Dog
Exception in thread "main" java.lang.NullPointerException
    at com.example.helloworldeclipse.Animal.main(

Shouldn’t isPresent be safe? is there a better way to cast abstract classes to subclasses in situations similar like this?

I don’t get why it’s not working.. What am I doing wrong here?

Thank you in advance for all the answers..


The problem is that you are assigning null to an Optional reference when the instanceof check fails.

You have at least two options:

  1. Use Optional.empty() instead of null

    Optional<Dog> dog = animal instanceof Dog ? Optional.of((Dog) animal) : Optional.empty();
  2. Use Optional’s filter and map methods:

    Optional<Dog> dog = Optional.of(animal)

    The predicate Dog.class::isInstance checks if the given instance, which is the value within the Optional, is an instance of Dog. This is equivalent to instanceof. Then Dog.class::cast casts the given object to a Dog instance.

Note: If animal itself could be null, then you should use Optional::ofNullable instead of Optional::of.

Source: stackoverflow