avatarVinotech

Summary

The Optional class in Java 8 provides a way to represent optional values, avoiding null checks and reducing the risk of NullPointerException.

Abstract

Java 8 introduced the Optional class as a container for values that may be absent, enhancing code safety and readability. Before Optional, developers had to manually check for null values, which could lead to NullPointerExceptions if not handled correctly. The Optional class offers methods such as of(), ofNullable(), get(), empty(), isPresent(), ifPresent(), orElse(), orElseGet(), and orElseThrow() to handle potential absent values in a more expressive and error-proof manner. By using Optional, developers are forced to confront the possibility of an absent value, thus reducing the chances of runtime exceptions due to null references. The article provides examples of how to use these methods with an Employee class, demonstrating the practical benefits of Optional in Java.

Opinions

  • The author suggests that using Optional is a superior alternative to returning null, as it leads to safer and more readable code.
  • The article implies that the explicit handling of optional values with Optional can significantly reduce the occurrence of NullPointerExceptions.
  • The author emphasizes the importance of understanding and correctly implementing Optional methods to fully leverage its benefits in Java applications.
  • By providing a comprehensive list of Optional class methods and examples, the author conveys that mastery of these methods is essential for modern Java development.
  • The encouragement to give claps and share the articles indicates the author's desire for reader engagement and recognition of the content's utility.

Optional in Java 8

Optional Class

Optional is a container class introduced in Java 8, designed to handle situations where a value may or may not be present. Instead of returning null, which can lead to NullPointerException when dereferenced, methods can return an Optional object. This approach forces developers to explicitly deal with the possibility of an absent value, thereby reducing the chances of runtime exceptions due to null references.

Before Java Optional, developers had to manually check if a value was null to handle NullPointerExceptions in Java applications. Imagine you have a method called getText() that returns a string, and you want to print its uppercase version to the console in the main method.

private static String getText() {
     String text = "Hello World";
     return text;
}
public static void main(String[] args) {
    System.out.println(getText().toUpperCase());
}

This works totally fine until, for some reason, the getText() function returns a null value. If you haven’t prepared for null values and you try to perform .toUpperCase() to a null value, you’ll get a NullPointerException in your program.

private static String getText() {
    String text = null;
    return text;
}

So the simplest solution to avoid a NullPointerException is to check if the value is null before performing any operations on it.

public static void main(String[] args) {
    if(getText()!=null)
        System.out.println(getText().toUpperCase());
    else
        System.out.println("Value is Null");
}

Optional class methods

  1. Optional.of() : Creates an Optional with a non-null value. Throws NullPointerException if the argument is null.
  2. Optional.ofNullable() : Creates an Optional that may or may not hold a non-null value. Doesn't throw an exception if the argument is null.
  3. get() : Returns the value if present; otherwise, throws NoSuchElementException.
  4. Optional.empty() : Represents an empty Optional instance, meaning no value is present.
  5. isPresent() : Returns true if there is a value present, otherwise false.
  6. ifPresent() : Performs the given action if a value is present.
  7. orElse() : Returns the value if present; otherwise, returns the specified default value.
  8. orElseGet() : Returns the value if present; otherwise, returns the result produced by the given supplier.
  9. orElseThrow() : Returns the value if present; otherwise, throws an exception created by the provided supplier.

Example : Optional class methods are implemented in this example.

Here’s the Employee class:

public class Employee {
    private String name;
    private int id;

    // Constructor
    public Employee(String name, int id) {
        this.name = name;
        this.id = id;
    }

    // Getters
    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    @Override
    public String toString() {
        return "Employee{name='" + name + "', id=" + id + "}";
    }
}

Now, let’s use various Optional methods with this Employee class:

import java.util.Optional;

public class OptionalExample {
    public static void main(String[] args) {
        // Create an Employee instance
        Employee emp1 = new Employee("John Doe", 123);
        Employee emp2 = null;

        // Optional.of() - Creates an Optional containing the given non-null value
        Optional<Employee> optionalEmp1 = Optional.of(emp1);
        System.out.println("Optional.of(emp1): " + optionalEmp1);
        //  Output: Optional[Employee{name='John Doe', id=123}]

        // Optional.ofNullable() - Creates an Optional containing the given value or empty if null
        Optional<Employee> optionalEmp2 = Optional.ofNullable(emp2);
        System.out.println("Optional.ofNullable(emp2): " + optionalEmp2);
        //  Output: Optional.empty

        // get() - Returns the value if present, otherwise throws NoSuchElementException
        System.out.println("optionalEmp1.get(): " + optionalEmp1.get());
        //  Output: Employee{name='John Doe', id=123}

        // Optional.empty() - Creates an empty Optional
        Optional<Employee> emptyOptional = Optional.empty();
        System.out.println("Optional.empty(): " + emptyOptional);
        // Output: Optional.empty

        // isPresent() - Checks if a value is present
        System.out.println("optionalEmp1.isPresent(): " + optionalEmp1.isPresent());
        // Output: true
        System.out.println("emptyOptional.isPresent(): " + emptyOptional.isPresent());
        // Output: false

        // ifPresent() - Executes the given action if a value is present
        optionalEmp1.ifPresent(emp -> System.out.println("Employee found: " + emp));
        // Output: Employee found: Employee{name='John Doe', id=123}
        optionalEmp2.ifPresent(emp -> System.out.println("This will not be printed"));
        // Output: (No output, since optionalEmp2 is empty)

        // orElse() - Returns the value if present, otherwise returns a default value
        Employee defaultEmp = new Employee("Default Employee", 0);
        System.out.println("optionalEmp2.orElse(defaultEmp): " + optionalEmp2.orElse(defaultEmp));
        // Output: Employee{name='Default Employee', id=0}

        // orElseGet() - Returns the value if present, otherwise calls a supplier function to get a default value
        System.out.println("optionalEmp2.orElseGet(() -> new Employee('Supplier Employee', 1)): " + optionalEmp2.orElseGet(() -> new Employee("Supplier Employee", 1)));
        // Output: Employee{name='Supplier Employee', id=1}

        // orElseThrow() - Returns the value if present, otherwise throws a custom exception
        try {
            System.out.println("optionalEmp2.orElseThrow(() -> new RuntimeException('No Employee found')): " + optionalEmp2.orElseThrow(() -> new RuntimeException("No Employee found")));
        } catch (RuntimeException e) {
            System.out.println(e.getMessage());
        }

        // Output: No Employee found (as an exception message)
    }
}

👏 If you found my articles useful, please consider giving it claps and sharing it with your friends and colleagues.

Optional Class
Java8
Nullpointerexception
Optionals
Optional In Java8
Recommended from ReadMedium