preface
Optional is a very important feature. Its main function is to solve the NPE(NullPointerException) problem!
Optional class
1. General
Optional is not a functional interface, but a beautiful tool to prevent NullPointerException. This is an important concept in the next section. Let's quickly understand the working principle of Optional.
Optional is a simple container whose value may or may not be null. Before Java 8, generally, a function should return a non empty object, but sometimes it returns nothing. In Java 8, you should return Optional instead of null.
2.API introduction
of
Create an Optional for a non null value.
The of() method creates an Optional class through a factory method. It should be noted that the parameters passed in when creating an object cannot be null. If the passed in parameter is null, a NullPointerException is thrown.
The code is as follows (example):
//Call the factory method to create an Optional instance Optional<String> stringOpt = Optional.of("Deer can be seen in the depth of the forest"); //If the passed in parameter is null, a java.lang.NullPointerException is thrown Optional<String> stringOpt1 = Optional.of(null);
ofNullable
Create an option for the specified value. If the specified value is null, an empty option will be returned.
ofNullable() is similar to the of method, except that it can accept null arguments.
The code is as follows (example):
//Create an Optional object that is allowed to be empty Optional opt = Optional.ofNullable(null); //No error will be reported
empty
An empty Optional.
The code is as follows (example):
//An empty Optional Optional<String> empty = Optional.empty();
isPresent
Returns true if the value exists; otherwise, returns false.
The code is as follows (example):
Optional<String> stringOpt = Optional.of("Deer can be seen in the depth of the forest"); //isPresent method returns true if the value exists; otherwise, it returns false. if (stringOpt.isPresent()) { //Call get() within the Optional instance to return an existing value System.out.println(stringOpt.get()); //Deer can be seen in the depth of the forest }
get
The code is as follows (example):
//An empty Optional Optional<String> empty = Optional.empty(); //Executing the following code will output: No value present try { //Call get() on an empty Optional instance and throw NoSuchElementException System.out.println(empty.get()); } catch (NoSuchElementException ex) { System.out.println(ex.getMessage()); }
ifPresent
If the Optional instance has a value, call consumer for it, otherwise it will not be processed
The code is as follows (example):
//The ifPresent method accepts a lambda expression as a parameter. The lambda expression calls consumer to process the value of Optional Optional.ofNullable(null).ifPresent(u -> System.out.println("yes null Yes, no treatment")); Optional.ofNullable("Deer can be seen in the depth of the forest").ifPresent(u -> System.out.println("no null Yes, deal with it")); //Output: not null, processing
Note: the value modified through ifPresent() will not change when obtained through get() again.
orElse
If there is a value, it will be returned; otherwise, it will return other specified values.
If the Optional instance has a value, it will be returned; otherwise, the parameter passed in by the orElse() method will be returned.
The code is as follows (example):
//If the value is not null, the orElse method returns the value of the Optional instance //If null, returns the passed in specified pointer Optional opt1 = Optional.ofNullable(null); Optional opt2 = Optional.ofNullable("Deer can be seen in the depth of the forest"); System.out.println(opt1.orElse("Specified value")); //Specified value System.out.println(opt2.orElse("Specified value")); //Deer can be seen in the depth of the forest
orElseGet
orElseGet() is similar to the orElse method, except that the default value is obtained. The orElse method takes the incoming string as the default value. The orElseGet method can accept the implementation of the Supplier interface to generate the default value.
The code is as follows (example):
//orElseGet is similar to orElse, except that orElseGet can accept a lambda expression to generate a default value Optional opt1 = Optional.ofNullable(null); Optional opt2 = Optional.ofNullable("Deer can be seen in the depth of the forest"); System.out.println(opt1.orElseGet( () -> "Specified value")); //Specified value System.out.println(opt2.orElseGet( () ->"Specified value")); //Deer can be seen in the depth of the forest
orElseThrow
If there is a value, it will be returned; otherwise, an exception created by the supplier interface will be thrown.
In the orElseGet method, we pass in a Supplier interface. However, in orElseThrow(), we can pass in a lambda expression or method to throw an exception if the value does not exist.
The code is as follows (example):
//Orelsethlow throws an exception generated by a lambda expression or method //An empty Optional Optional<String> empty = Optional.empty(); try { empty.orElseThrow( () -> new Exception() ); } catch (Throwable ex) { ex.printStackTrace(); }
map
If there is a value, call the mapping function to get the return value. If the return value is not null, an option containing the mapping return value is created as the return value of the map() method; otherwise, an empty option is returned.
The code is as follows (example):
//Map executes the passed lambda expression parameter to modify the value of the Optional instance. The return value of the lambda expression creates a new Optional instance as the return value of the map method Optional<String> stringOpt = Optional.of("aBcDefg"); Optional<String> upperName = stringOpt.map((value) -> value.toUpperCase()); System.out.println(upperName.orElse("No value found")); //Output: ABCDEFG
flatMap
If there is a value, execute the mapping function for it to return the return value of Optional type; otherwise, it returns null Optional. The flatMap() method is similar to the map (function) method, except that the mapper return value in the flatMap must be Optional. At the end of the call, flatMap does not optionally encapsulate the results.
The code is as follows (example):
//flatMap is very similar to map (Function), except for the return type of the lambda expression passed into the method //The return value of the lambda expression in the flatMap method must be an Optional instance Optional<String> stringOpt = Optional.of("aBcDefg"); Optional<String> upperName = stringOpt.flatMap((value) -> Optional.of(value.toUpperCase())); System.out.println(upperName.orElse("No value found")); //Output: ABCDEFG
filter
If there is a value and the assertion condition is met, the option containing the value is returned; otherwise, the empty option is returned.
The code is as follows (example):
//The filter method checks whether the given Option value meets some conditions. If so, it returns the same Option instance. Otherwise, it returns null Option Optional<Integer> intOpt = Optional.of(5); Optional<Integer> longName = intOpt.filter((value) -> value > 6); System.out.println(longName.orElse(0)); //0
3.Optional application
- Optional.of(obj): it requires that the incoming obj cannot be null, otherwise it will fall on the NullPointerException exception before entering the role
- Optional.ofNullable(obj): it constructs an optional instance in an intelligent and tolerant way. Whoever comes will get Optional.empty(). If it is not null, it will call Optional.of(obj)
The code is as follows (example):
Optional<User> user = Optional.of(user1); //orElse() map() may be concatenated infinitely to obtain the uppercase form of the user name. Otherwise, the default value is null return user.map(u -> u.getUsername()) .map(name -> name.toUpperCase()) .orElse(null); //orElseGet() is similar to orElse(), except that it uses a functional interface without a value User result = Optional.ofNullable(user1).orElseGet( () -> user2); //orElseThrow() if the user value is null, an IllegalArgumentException will be thrown User result = Optional.ofNullable(user) .orElseThrow( () -> new IllegalArgumentException()); //The filter() decides to accept or reject the User based on basic email authentication Optional<User> result = Optional.ofNullable(user) .filter(u -> u.getEmail() != null && u.getEmail().contains("@"));
When we want to assert that obj is not null, that is, we want to immediately report a NullPointException exception in case obj is null and modify it immediately instead of hiding the null pointer exception, we should decisively use option. Of (obj) to construct the Optional instance, and do not let any unpredictable null value have an opportunity to hide in Optional.
@Data public class Student { private String name = "Deer can be seen in the depth of the forest"; private String sex = "male"; } // 1. Create an Optional object with an empty wrapper object value Optional<Student> studentOpt = Optional.empty(); // 2. Create an Optional object with a non empty wrapper object value Optional<Student> studentOpt1 = Optional.of(new Student()); // 3. Create an Optional object whose wrapper object value is allowed to be empty Optional<Student> studentOpt2 = Optional.ofNullable(null); System.out.println(studentOpt.get().getName()); // Printing: NoSuchElementException System.out.println(studentOpt.orElse(new Student()).getName()); // Print: Deer in deep forest System.out.println(studentOpt1.get().getName()); // Print: Deer in deep forest System.out.println(studentOpt2.get().getName()); // Printing: NoSuchElementException System.out.println(studentOpt2.orElse(new Student()).getName()); // Print: Deer in deep forest System.out.println(studentOpt.isPresent()); // Print: false System.out.println(studentOpt1.isPresent()); // Print: true
Optional can create objects of any type and obtain specific objects through the get() method. When the creation option is empty, the obtained object is empty, but it can be judged by orElse. If it is empty, it can be re created through orElse parameters. The isPresent() method is used to determine whether the object encapsulated by option is empty.
Student studentNull = null; Student student = new Student(); Optional.ofNullable(studentNull).ifPresent(u -> System.out.println("This object is null of")); Optional.ofNullable(student).ifPresent(u -> System.out.println("Is this object null of")); //Output: is this object NULL
The ifPresent() method accepts a Consumer object (Consumer function). If the value of the wrapper object is not empty, run the accept() method of the Consumer object. In this way, you can happily use Lambda expressions.
Optional.ofNullable(studentNull) .filter(u -> "Deer can be seen in the depth of the forest".equals(u.getName())) .ifPresent(u -> System.out.println("studentNull,The name is equal to the goal of "seeing deer in the deep forest"")); Optional.ofNullable(student) .filter(u -> "Deer can be seen in the depth of the forest".equals(u.getName())) .ifPresent(u -> System.out.println("student,The name is equal to the goal of "seeing deer in the deep forest"")); Optional.ofNullable(student) .filter(u -> "Zhang San".equals(u.getName())) .ifPresent(u -> System.out.println("student,The name is equal to the goal of "Zhang San"")); //Output: student, whose name is equal to the target of "deer in the deep forest"
The filter() method is also very practical. This method is used to filter the Optional object. If the conditions are met, the Optional object itself is returned. Otherwise, an empty Optional object is returned.
System.out.println(Optional.ofNullable(student).map(u -> u.getName()).get()); System.out.println(Optional.ofNullable(studentNull).map(u -> u.getName())); //u.getName()).get() will report an error //Output: //Deer can be seen in the depth of the forest //Optional.empty System.out.println(Optional.ofNullable(student).map(u -> u.getName()).orElse("This may be empty")); System.out.println(Optional.ofNullable(studentNull).map(u -> u.getName()).orElse("This must be empty")); //Output: //Deer can be seen in the depth of the forest //This must be empty
First, construct an Optional object with ofNullable() method and return the Optional object (if the student is null, return the map() method and return an empty Optional object). If u.getName()).get() cannot get, an exception will occur, so orElse is used instead.
Use the orElse method to replace the get method. The function of the orElse() method is relatively simple, that is, if the wrapped object value is not empty, return the wrapped object value, otherwise return the value of the input parameter other (the default value).