Core Java

Java 8 Optional In Depth Example

1. Introduction

This is an in-depth article about Java 8 Optional. A new class Optional was introduced in Java 8. The optional class is part of java.util package. Optional is used to represent a value. It can be present or absent. No more null checks and NullPointerException are needed. Optional helps in avoiding any runtime NullPointerExceptions. It helps in developing clean and neat Java APIs. Optional Object is also a Container which holds at most one value. The Advantages of Optional are Null checks, NullPointerException at run-time not required and no more boiler plate code.

2. Optional In Depth

The Optional class is used to make a field optional. The field may or may not have values.

2.1 Creation of Optionals

Optional objects can be created using empty, of and ofNullable methods.

2.1.1 Empty method

The following code snippet shows how to create an Optional object using empty method:

Creating Optional Empty

import java.util.Optional;

public class  OptionalCreator
{

   public Optional getEmptyOptional() {
    Optional empty = Optional.empty();
    return empty;
   }
  public static void main(String[] args)
  {
     OptionalCreator creator = new OptionalCreator();
     Optional empty = creator.getEmptyOptional();
     
     System.out.println(empty.isPresent());
  }
}

The command below executes the above code snippet:

Run command

 
javac OptionalCreator.java

java OptionalCreator

The output of the executed command is shown below.

Java 8 Optional In Depth - OptionalCreator
OptionalCreator

2.1.2 of Method

An Optional object can be created using Of method. The code snippet below shows the implementation :

OptionalOfCreator

import java.util.Optional;

public class  OptionalOfCreator
{

   public Optional  GetOptionalOf() {
    String name = "optioncheck";
    Optional opt = Optional.of(name);
    return opt;       
   }
  public static void main(String[] args)
  {
     OptionalOfCreator creator = new OptionalOfCreator();
     Optional opt = creator.GetOptionalOf();
     
     System.out.println(opt.toString());
  }
}

The command below executes the above code snippet:

Run command

 
javac OptionalOfCreator.java

java OptionalOfCreator

The output of the executed command is shown below.

Java 8 Optional In Depth - OptionalOf Creator
OptionalOf Creator

2.1.3 ofNullable

An Optional object can be created using ofNullable method. The code snippet below shows the implementation :

OptionalOfNullableCreator

import java.util.Optional;

public class  OptionalOfNullableCreator
{


  public Optional getNullable() {
    String name = "optioncheck";
    Optional opt = Optional.ofNullable(name);
    return opt;   
  }    
  public static void main(String[] args)
  {
     OptionalOfNullableCreator creator = new OptionalOfNullableCreator();
     Optional opt = creator.getNullable();
     
     System.out.println(opt.toString());
  }
}

The command below executes the above code snippet:

Run command

 
javac OptionalOfNullableCreator.java

java OptionalOfNullableCreator

The output of the executed command is shown below.

Java 8 Optional In Depth - OptionalOfNullableCreator
OptionalOfNullableCreator

2.2 Checking Value

An Optional object’s value can be checked using isPresent method. IsEmpty can be used if you want to check if object is empty. The sections below show the isPresent implementation.

2.2.1 Optional created using of method

The code snippet below shows the implementation for checking value for optional created using of method:

OptionalEmptyChecker

import java.util.Optional;

public class  OptionalEmptyChecker
{


  public Optional getOptionalOf() {
    Optional opt = Optional.of("Option Empty");
    
    return opt;
}
     
  public static void main(String[] args)
  {
     OptionalEmptyChecker creator = new OptionalEmptyChecker();
     Optional opt = creator.getOptionalOf();
     
     System.out.println(opt.isPresent());
  }
}

The command below executes the above code snippet:

Run command

 
javac OptionalEmptyChecker.java

java OptionalEmptyChecker

The output of the executed command is shown below.

Java 8 Optional In Depth - OptionalEmptyChecker
OptionalEmptyChecker

2.2.2 Optional created using ofNullable method

The code snippet below shows the implementation for checking value for optional created using of method:

OptionalNullableEmptyChecker

import java.util.Optional;

public class  OptionalNullableEmptyChecker
{


  public Optional getNullable() {
    
    Optional  opt = Optional.ofNullable(null);
    return opt;
}
     
  public static void main(String[] args)
  {
     OptionalNullableEmptyChecker creator = new OptionalNullableEmptyChecker();
     Optional opt = creator.getNullable();
     
     System.out.println(opt.isPresent());
  }
}

The command below executes the above code snippet:

Run command

 
javac OptionalNullableEmptyChecker.java

java OptionalNullableEmptyChecker

The output of the executed command is shown below.

Java 8 Optional In Depth - OptionalNullableEmptyChecker
OptionalNullableEmptyChecker

2.3 Defaults

The orElseGet method is used to get the default value which is the Optional The code snippet below shows the implementation of using orElseGet method:

OptionalOfNullOrElseGetChecker

public class  OptionalOfNullOrElseGetChecker
{

  public String getNullable() {
    String name = null;
    String opt = Optional.ofNullable(name).orElseGet(() ->"value");
    return opt; 
  }    
  public static void main(String[] args)
  {
     OptionalOfNullOrElseGetChecker creator = new OptionalOfNullOrElseGetChecker();
     String opt = creator.getNullable();
     
     System.out.println(opt);
  }
}

The command below executes the above code snippet:

Run command

 
javac OptionalOfNullOrElseGetChecker.java

java OptionalOfNullOrElseGetChecker

The output of the executed command is shown below.

OptionalOfNullOrElseGetChecker

2.4 Exception Handling

The orElseThrow method handles an absent value by throwing exception. The code snippet below shows the implementation of using orElseThrow method:

OptionalOfNullOrElseThrowChecker

import java.util.Optional;

public class  OptionalOfNullOrElseThrowChecker
{

  public void throwElseException() throws Exception {
    String nullName = null;
    String name = Optional.ofNullable(nullName).orElseThrow(
      IllegalArgumentException::new);
  }   
  public static void main(String[] args) throws Exception
  {
     OptionalOfNullOrElseThrowChecker creator = new OptionalOfNullOrElseThrowChecker();
      creator.throwElseException();
     
   
  }
}

The command below executes the above code snippet:

Run command

 
javac OptionalOfNullOrElseThrowChecker.java

java OptionalOfNullOrElseThrowChecker

The output of the executed command is shown below.

OptionalOfNullOrElseThrowChecker

2.5 Value Return

Get method is used to return the optional value. The code snippet below shows the implementation of using get method:

OptionalOfGetChecker

import java.util.Optional;

public class  OptionalOfGetChecker
{

   public Optional  getOptional() {
    String name = "optioncheck";
    Optional opt = Optional.of(name);
    return opt;       
   }
  public static void main(String[] args)
  {
     OptionalOfGetChecker creator = new OptionalOfGetChecker();
     Optional opt = creator.getOptional();
     
     System.out.println(opt.get());
  }
}

The command below executes the above code snippet:

Run command

 
javac OptionalOfGetChecker.java

java OptionalOfGetChecker

The output of the executed command is shown below.

OptionalOfGetChecker

2.6 Filtering

The filter method is used to filter the optionals based on the predicate. The code snippet below shows the implementation of using filter method:

OptionalFilter

import java.util.Optional;

public class OptionalFilter {
    
    public Optional getOptional() {
      String name = "optioncheck";
      Optional opt = Optional.of(name);
     return opt;  
    }    

    public static void main(String[] args) {
        
        OptionalFilter optional = new OptionalFilter();

        Optional opt = optional.getOptional();
        System.out.println(opt.filter(name -> name.equals("optioncheck"))); 


    }

}

The command below executes the above code snippet:

Run command

 
javac OptionalFilter.java

java OptionalFilter

The output of the executed command is shown below.

OptionalFilter

2.8 Map Optional for transforming

The map method is used for transforming the Optional value. The code snippet below shows the implementation of using the map method:

OptionalMap

import java.util.Optional;
import java.util.List;
import java.util.Arrays;

public class OptionalMap {
    
    
    public Optional<List> getOptional() {
       List companies = Arrays.asList(
      "ibm", "oracle", "Qubit", "microsoft", "", "google");
    Optional<List> opt = Optional.of(companies);
      return opt;   
   }

  public static void main(String[] args) {
      
        OptionalMap optional = new OptionalMap();
      
        Optional<List> opt = optional.getOptional();


        int size = opt.map(List::size).orElse(0);
        
        System.out.println(size);
    }
    
}

The command below executes the above code snippet:

Run command

 
javac OptionalMap.java

java OptionalMap

The output of the executed command is shown below.

OptionalMap

2.9 Optional Chains

Stream class is used to chain Optional objects. The code snippet below shows the implementation of using the Stream class:

OptionChain

import java.util.Optional;
import java.util.stream.*;

public class  OptionChain
{

    private Optional getEmpty() {
        return Optional.empty();
    }

    public Optional getCheck() {
        return Optional.of("check");
    }

    private Optional getExit() {
        return Optional.of("exit");
    }

    private Optional createOptional(String value) {
        if (value == null || value == "" || value == "empty") {
            return Optional.empty();
        }
        return Optional.of(value);
    }
    
    public void getChain() {
      Optional found = Stream.of(getEmpty(), getCheck(), getExit())
      .filter(Optional::isPresent)
      .map(Optional::get)
      .findFirst();
     
    
   }
    
    public static void main(String[] args)
    {
    
        OptionChain chain = new OptionChain();
        
        chain.getChain();
        
        Optional opt = chain.getCheck();
        
        System.out.println(opt.toString());
        
        
        
    }
    
}

The command below executes the above code snippet:

Run command

 
javac OptionChain.java

java OptionChain

The output of the executed command is shown below.

OptionChain

2.10 Java Standalone Application

A java standalone application is presented to show the implementation of Optional in the application features. Without using optional, the application is presented first.

2.10.1 No Optional

ImageSize, ImageFeatures, Photo, PhotoService and PhotoTesterNoOption classes are part of the photo management application.

The code snippet below shows the ImageFeatures class.

Image Features

public class ImageFeatures {

	private String fileSize; 
	private ImageSize imageSize;
	
	public ImageFeatures(String size, ImageSize imageSize){
		this.fileSize = size;
		this.imageSize = imageSize;
	}
	
	public String getFileSize() {
		return fileSize;
	}
	public ImageSize getImageSize() {
		return imageSize;
	}
	
}

The code snippet below shows the ImageSize class.

ImageSize

public class ImageSize {

	private int width;
	private int height;
	
	public ImageSize(int width, int height){
		this.width = width;
		this.height = height;
	}
	
	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}
	
}

The code snippet below shows the Photo class.

Photo

public class Photo {

	private long id;
	private String company;
	private String name;
	private ImageFeatures features;
	
	public Photo(long id, String company, String name, 
                            ImageFeatures features){
		this.id = id;
		this.company = company;
		this.name = name;
		this.features = features;
	}

	public long getId() {
		return id;
	}

	public String getCompany() {
		return company;
	}

	public String getName() {
		return name;
	}

	public ImageFeatures getFeatures() {
		return features;
	}
	
}

The code snippet below shows the PhotoService class.

PhotoService

public class PhotoService {
	
	public int getPhotoScreenWidth(Photo photo){

		if(photo != null){
			ImageFeatures features = photo.getFeatures();
			if(features != null){
				ImageSize size = features.getImageSize();
				if(size != null){
					return size.getWidth();
				}
			}
		}
		return 0;

	}

}

The code snippet below shows the PhotoTesterNoOption class.

PhotoTesterNoOption

public class PhotoTesterNoOption {
	
	public static void main(String[] args) {

		ImageSize size = new ImageSize(750,1334);
		ImageFeatures features = new ImageFeatures("8.7", size);
		Photo photo = new Photo(31591, "Google", "pixel", features);
		
		PhotoService photoService = new PhotoService();
		
		int width = photoService.getPhotoScreenWidth(photo);
		System.out.println(" Width = " + width);
		
		
	}

}

The command below executes the above code snippet:

Run command

 
javac PhotoTesterNoOption.java

java PhotoTesterNoOption

The output of the executed command is shown below.

PhotoTesterNoOption

2.10.2 With Optional

ImageSize, ImageFeatures, Photo, PhotoService and PhotoTesterOption classes are part of the photo management application in which Optionals are used.

The code snippet below shows the ImageFeatures class.

ImageFeatures

import java.util.Optional;
public class ImageFeatures {

	private String fileSize; 
	private Optional imageSize;
	
	public ImageFeatures(String size, Optional imageSize){
		this.fileSize = size;
		this.imageSize = imageSize;
	}
	
	public String getFileSize() {
		return fileSize;
	}
	public Optional getImageSize() {
		return imageSize;
	}
	
}

The code snippet below shows the ImageSize class.

Image Size

public class ImageSize {

	private int width;
	private int height;
	
	public ImageSize(int width, int height){
		this.width = width;
		this.height = height;
	}
	
	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}
	
}

The code snippet below shows the Photo class.

Photo

import java.util.Optional;
public class Photo {

	private long id;
	private String company;
	private String name;
	private Optional features;
	
	public Photo(long id, String company, String name, 
                            Optional features){
		this.id = id;
		this.company = company;
		this.name = name;
		this.features = features;
	}

	public long getId() {
		return id;
	}

	public String getCompany() {
		return company;
	}

	public String getName() {
		return name;
	}

	public Optional getFeatures() {
		return features;
	}
	
}

The code snippet below shows the PhotoService class.

PhotoService

import java.util.Optional;
public class PhotoService {
	
	public int getPhotoScreenWidth(Optional photo){

		return photo.flatMap(Photo::getFeatures)
		 .flatMap(ImageFeatures::getImageSize)
		 .map(ImageSize::getWidth)
		 .orElse(0);

	}

}

The code snippet below shows the PhotoTesterOption class.

PhotoTesterOption

import java.util.Optional;
public class PhotoTesterOption {
	
	public static void main(String[] args) {

		ImageSize size = new ImageSize(750,1334);
		ImageFeatures features = new ImageFeatures("8.7", Optional.of(size));
		Photo photo = new Photo(31591, "Google", "pixel", Optional.of(features));
		
		PhotoService photoService = new PhotoService();
		
		int width = photoService.getPhotoScreenWidth(Optional.of(photo));
		System.out.println(" Width = " + width);
		
		
	}

}

The command below executes the above code snippet:

Run command

 
javac PhotoTesterOption.java

java PhotoTesterOption

The output of the executed command is shown below.

PhotoTesterOption

2.11 Best Practices

You should not assign null to an Optional object. Developer should assign a value to Optional Object before invoking get(). Use orElse method when optional default object has no value. You can use orElseGet to return a non existent optional object. ElseThrow method can be used when there is no value assigned to Optional Object. You can use orElse method when an Optional has a Null Reference.

You can consume an Optional if the value is not empty. Developer need not do anything if the value is empty. Chaining can be avoided if the goal is to get a value. You should avoid declaring a field of type Optional. Avoid using optional in arguments of the constructors and methods. You should not implement optional in collections. Values need to be transformed using map and flatmap methods. Filter method is used to reject the values based on a rule.

Developer should not use optionals in the operations which are sensitive on identity. For asserting equality, you need not unwrap optionals. You should not use Optional<T>. Developer can use OptionalInt, OptionalLong, or OptionalDouble classes which are not generic.

3. Download the Source Code

Download
You can download the full source code of this example here: Java 8 Optional In Depth Example

Bhagvan Kommadi

Bhagvan Kommadi is the Founder of Architect Corner & has around 20 years’ experience in the industry, ranging from large scale enterprise development to helping incubate software product start-ups. He has done Masters in Industrial Systems Engineering at Georgia Institute of Technology (1997) and Bachelors in Aerospace Engineering from Indian Institute of Technology, Madras (1993). He is member of IFX forum,Oracle JCP and participant in Java Community Process. He founded Quantica Computacao, the first quantum computing startup in India. Markets and Markets have positioned Quantica Computacao in ‘Emerging Companies’ section of Quantum Computing quadrants. Bhagvan has engineered and developed simulators and tools in the area of quantum technology using IBM Q, Microsoft Q# and Google QScript. He has reviewed the Manning book titled : "Machine Learning with TensorFlow”. He is also the author of Packt Publishing book - "Hands-On Data Structures and Algorithms with Go".He is member of IFX forum,Oracle JCP and participant in Java Community Process. He is member of the MIT Technology Review Global Panel.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button