Detailed explanation of the Optional class that comes with Java8

Use Java 8 ’s new feature Optional instead of if-else to solve the null pointer problem

static constructor

JDK provides three static methods to construct an `Optional`


    
    
     
     
  1. public final class Optional<T> {
  2. private static final Optional<?> EMPTY = new Optional<>();
  3. private final T value;
  4. // This method is used to construct an empty Optional. If the value in the Optional is null, the Optional will not contain a value.
  5. public static<T> Optional<T> empty () {
  6. @SuppressWarnings("unchecked")
  7. Optional<T> t = (Optional<T>) EMPTY;
  8. return t;
  9. }
  10. //Construct an Optional through a non-null value,
  11. //The returned Optional contains the value value. For this method, the parameters passed in must not be null, otherwise NullPointerException will be thrown.
  12. public static <T> Optional<T> of (T value) {
  13. return new Optional<>(value);
  14. }
  15. //The difference between this method and of method is that the parameter passed in can be null. If it is null, Optional.empty() is returned.
  16. public static <T> Optional<T> ofNullable (T value) {
  17. return value == null ? empty() : of(value);
  18. }
  19. }

Common methods

isPresent() / ifPresent()


    
    
     
     
  1. // Return true if the value exists, false otherwise
  2. public boolean isPresent () {
  3. return value != null;
  4. }
  5. // If the Optional instance has a value, call consumer for it, otherwise no processing will be done.
  6. public void ifPresent (Consumer<? super T> consumer) {
  7. if (value != null)
  8. consumer.accept(value);
  9. }

test


    
    
     
     
  1. public class OptionalTest {
  2. public static void main (String[] args) {
  3. User user = new User();
  4. Optional<User> optional = Optional.ofNullable(user);
  5. optional.ifPresent(s -> System.out.println(s));
  6. }
  7. }

Get()

Get the value in Optional, which is our value. Optional is equivalent to a shell.


    
    
     
     
  1. public T get () {
  2. if (value == null) {
  3. throw new NoSuchElementException( "No value present");
  4. }
  5. return value;
  6. }

orElse() / orElseGet() / orElseThrow()


    
    
     
     
  1. // If the value in Optional is not empty, return the value in Optional. If it is empty, return the other value.
  2. public T orElse (T other) {
  3. return value != null ? value : other;
  4. }
  5. // If there is a value in Optional, return the value, otherwise return the result of other call
  6. public T orElseGet (Supplier<? extends T> other) {
  7. return value != null ? value : other.get();
  8. }
  9. // If the value in Optional exists, the value is returned. If the value does not exist, the exception in the exception function Supplier is thrown.
  10. public <X extends Throwable> T orElseThrow (Supplier<? extends X> exceptionSupplier) throws X {
  11. if (value != null) {
  12. return value;
  13. } else {
  14. throw exceptionSupplier.get();
  15. }
  16. }

test


    
    
     
     
  1. String value = "2";
  2. String orElse = Optional.ofNullable(value).orElse( "1");
  3. System.out.println(orElse); //2
  4. String value = null;
  5. String orElse = Optional.ofNullable(value).orElse( "1");
  6. System.out.println(orElse); //1
  7. -------------------------------------------------------
  8. public class OptionalTest {
  9. public static void main (String[] args) {
  10. String value = null;
  11. String orElse = Optional.ofNullable(value).orElseGet(OptionalTest::get);
  12. System.out.println(orElse); // 123
  13. String value = "2";
  14. String orElse = Optional.ofNullable(value).orElseGet(OptionalTest::get);
  15. System.out.println(orElse); // 2
  16. }
  17. public static String get (){
  18. return "123";
  19. }
  20. }
  21. -------------------------------------------------------
  22. public class OptionalTest {
  23. public static void main (String[] args) {
  24. String value = null;
  25. String orElse = Optional.ofNullable(value).orElseThrow(() -> new RuntimeException ( "Value does not exist" ));
  26. System.out.println(orElse);
  27. }
  28. }

map() / flatMap()

  • map(Function): If  Optional  is not empty, apply  Function  to  the content in Optional  and return the result. Otherwise, Optional.empty is returned directly  .

  • flatMap(Function):Same  map(), but the provided mapping function wraps the result in  an Optional  object, so  flatMap() no wrapping is done at the end.

None of the above methods are applicable to numeric  Optional . Generally speaking, streams  filter() will   remove stream elements when Predicate  returns  . The Optionalfalse will not  Optional.filter() be deleted on failure  , but will be retained and converted to empty.


    
    
     
     
  1. // Pass the value in Optional as a parameter to map. If the value passed in is empty, an empty Optional object is returned, which is equivalent to Optional.empty(),
  2. // If it is not empty, we can return a return value that can describe the result (the value in Optional, this value can be reassigned)
  3. public<U> Optional<U> map (Function<? super T, ? extends U> mapper) {
  4. Objects.requireNonNull(mapper);
  5. if (!isPresent())
  6. return empty();
  7. else {
  8. return Optional.ofNullable(mapper.apply(value));
  9. }
  10. }
  11. // If the value in Optional exists, then return a value based on Optional (such as Optional),
  12. // If the value in Optional does not exist, an empty Optional object is returned, equivalent to Optional.empty(),
  13. // Unlike map, map returns a value, while flatMap returns a value based on Optional
  14. public<U> Optional<U> flatMap (Function<? super T, Optional<U>> mapper) {
  15. Objects.requireNonNull(mapper);
  16. if (!isPresent())
  17. return empty();
  18. else {
  19. return Objects.requireNonNull(mapper.apply(value));
  20. }
  21. }

test


    
    
     
     
  1. public class OptionalTest {
  2. public static void main (String[] args) {
  3. User user = null;
  4. Optional<String> optional = Optional.ofNullable(user).map(OptionalTest::getMap);
  5. System.out.println(optional); //Optional.empty
  6. User user = new User();
  7. user.setUsername( "Admin");
  8. Optional<String> optional = Optional.ofNullable(user).map(OptionalTest::getMap);
  9. System.out.println(optional); // Optional[Admin]
  10. }
  11. public static String getMap (User user){
  12. return user.getUsername();
  13. }
  14. -------------------------------------------------------
  15. User user = new User();
  16. user.setUsername( "Admin");
  17. Optional<String> optional = Optional.ofNullable(user).flatMap(OptionalTest::getFlatMap);
  18. System.out.println(optional);
  19. } ​
  20. public static Optional<String> getFlatMap (User user){
  21. return Optional.ofNullable(user).map(User::getUsername);
  22. }

filter()

Pass the value in Optional as a parameter. If it meets the rules, an Optional object is returned, otherwise an empty Optional object (Optional.empty) is returned.


    
    
     
     
  1. public Optional<T> filter (Predicate<? super T> predicate) {
  2. Objects.requireNonNull(predicate);
  3. if (!isPresent())
  4. return this;
  5. else
  6. return predicate.test(value) ? this : empty();
  7. }

Actual combat

ifPresent(), this is a terminal operation. If the value exists, the specified consumption method will be called.


    
    
     
     
  1. // Get the value of book, if book is null, return the default value
  2. String book = Optional.ofNullable(person).map(Person::getBook).orElse( "default");
  3. // If person is not null, print salary
  4. Optional.ofNullable(person).ifPresent(p -> System.out.println(p.getSalary()));
  5. ​// If book is null, set the default value
  6. Optional.ofNullable(person)
  7. .map(Person::getComputer)
  8. .ifPresent(c -> c.setBrandName( "default name"));
  9. Optional.ofNullable(person)
  10. .map(Person::getComputer)
  11. .ifPresent( this::consumerTest);
  12. public void consumerTest (Computer computer){
  13. System.out.println( "consumer test");
  14. System.out.println(computer);
  15. }
  16. // Get brand, if brandName is "", throw an exception
  17. // Because map can only filter out null values, and we usually need to make other judgments at work, we can use map to parse a certain attribute in the entity class, and then use filter to perform corresponding filtering.
  18. String brand = Optional.ofNullable(person)
  19. .map(Person::getComputer)
  20. .map(Computer::getBrandName)
  21. .filter(b -> !b.equals( ""))
  22. .orElseThrow(() -> new NumberFormatException ( "Brand is empty" ));
  23. System.out.println( "brand: " + brand);

Use Java 8 ’s new feature Optional instead of if-else to solve the null pointer problem

static constructor

JDK provides three static methods to construct an `Optional`


    
    
  
  
  1. public final class Optional<T> {
  2. private static final Optional<?> EMPTY = new Optional<>();
  3. private final T value;
  4. // This method is used to construct an empty Optional. If the value in the Optional is null, the Optional will not contain a value.
  5. public static<T> Optional<T> empty () {
  6. @SuppressWarnings("unchecked")
  7. Optional<T> t = (Optional<T>) EMPTY;
  8. return t;
  9. }
  10. //Construct an Optional through a non-null value,
  11. //The returned Optional contains the value value. For this method, the parameters passed in must not be null, otherwise NullPointerException will be thrown.
  12. public static <T> Optional<T> of (T value) {
  13. return new Optional<>(value);
  14. }
  15. //The difference between this method and of method is that the parameter passed in can be null. If it is null, Optional.empty() is returned.
  16. public static <T> Optional<T> ofNullable (T value) {
  17. return value == null ? empty() : of(value);
  18. }
  19. }

Common methods

isPresent() / ifPresent()


    
    
  
  
  1. // Return true if the value exists, false otherwise
  2. public boolean isPresent () {
  3. return value != null;
  4. }
  5. // If the Optional instance has a value, call consumer for it, otherwise no processing will be done.
  6. public void ifPresent (Consumer<? super T> consumer) {
  7. if (value != null)
  8. consumer.accept(value);
  9. }

test


    
    
  
  
  1. public class OptionalTest {
  2. public static void main (String[] args) {
  3. User user = new User();
  4. Optional<User> optional = Optional.ofNullable(user);
  5. optional.ifPresent(s -> System.out.println(s));
  6. }
  7. }

Get()

Get the value in Optional, which is our value. Optional is equivalent to a shell.


    
    
  
  
  1. public T get () {
  2. if (value == null) {
  3. throw new NoSuchElementException( "No value present");
  4. }
  5. return value;
  6. }

orElse() / orElseGet() / orElseThrow()


    
    
  
  
  1. // If the value in Optional is not empty, return the value in Optional. If it is empty, return the other value.
  2. public T orElse (T other) {
  3. return value != null ? value : other;
  4. }
  5. // If there is a value in Optional, return the value, otherwise return the result of other call
  6. public T orElseGet (Supplier<? extends T> other) {
  7. return value != null ? value : other.get();
  8. }
  9. // If the value in Optional exists, the value is returned. If the value does not exist, the exception in the exception function Supplier is thrown.
  10. public <X extends Throwable> T orElseThrow (Supplier<? extends X> exceptionSupplier) throws X {
  11. if (value != null) {
  12. return value;
  13. } else {
  14. throw exceptionSupplier.get();
  15. }
  16. }

test


    
    
  
  
  1. String value = "2";
  2. String orElse = Optional.ofNullable(value).orElse( "1");
  3. System.out.println(orElse); //2
  4. String value = null;
  5. String orElse = Optional.ofNullable(value).orElse( "1");
  6. System.out.println(orElse); //1
  7. -------------------------------------------------------
  8. public class OptionalTest {
  9. public static void main (String[] args) {
  10. String value = null ;
  11. String orElse = Optional.ofNullable(value).orElseGet(OptionalTest::get);
  12. System.out.println(orElse); // 123
  13. String value = "2";
  14. String orElse = Optional.ofNullable(value).orElseGet(OptionalTest::get);
  15. System.out.println(orElse); // 2
  16. }
  17. public static String get (){
  18. return "123";
  19. }
  20. }
  21. -------------------------------------------------------
  22. public class OptionalTest {
  23. public static void main (String[] args) {
  24. String value = null;
  25. String orElse = Optional.ofNullable(value).orElseThrow(() -> new RuntimeException ( "Value does not exist" ));
  26. System.out.println(orElse);
  27. }
  28. }

map() / flatMap()

  • map(Function): If  Optional  is not empty, apply  Function  to  the content in Optional  and return the result. Otherwise, Optional.empty is returned directly  .

  • flatMap(Function):Same  map(), but the provided mapping function wraps the result in  an Optional  object, so  flatMap() no wrapping is done at the end.

None of the above methods are applicable to numeric  Optional . Generally speaking, streams  filter() will   remove stream elements when Predicate  returns  . The Optionalfalse will not  Optional.filter() be deleted on failure  , but will be retained and converted to empty.


    
    
  
  
  1. // Pass the value in Optional as a parameter to map. If the value passed in is empty, an empty Optional object is returned, which is equivalent to Optional.empty(),
  2. // If it is not empty, we can return a return value that can describe the result (the value in Optional, this value can be reassigned)
  3. public<U> Optional<U> map (Function<? super T, ? extends U> mapper) {
  4. Objects.requireNonNull(mapper);
  5. if (!isPresent())
  6. return empty();
  7. else {
  8. return Optional.ofNullable(mapper.apply(value));
  9. }
  10. }
  11. // If the value in Optional exists, then return a value based on Optional (such as Optional),
  12. // If the value in Optional does not exist, an empty Optional object is returned, equivalent to Optional.empty(),
  13. // Unlike map, map returns a value, while flatMap returns a value based on Optional
  14. public<U> Optional<U> flatMap (Function<? super T, Optional<U>> mapper) {
  15. Objects.requireNonNull(mapper);
  16. if (!isPresent())
  17. return empty();
  18. else {
  19. return Objects.requireNonNull(mapper.apply(value));
  20. }
  21. }

test


    
    
  
  
  1. public class OptionalTest {
  2. public static void main (String[] args) {
  3. User user = null;
  4. Optional<String> optional = Optional.ofNullable(user).map(OptionalTest::getMap);
  5. System.out.println(optional); //Optional.empty
  6. User user = new User();
  7. user.setUsername( "Admin");
  8. Optional<String> optional = Optional.ofNullable(user).map(OptionalTest::getMap);
  9. System.out.println(optional); // Optional[Admin]
  10. }
  11. public static String getMap (User user){
  12. return user.getUsername();
  13. }
  14. -------------------------------------------------------
  15. User user = new User();
  16. user.setUsername( "Admin");
  17. Optional<String> optional = Optional.ofNullable(user).flatMap(OptionalTest::getFlatMap);
  18. System.out.println(optional);
  19. } ​
  20. public static Optional<String> getFlatMap (User user){
  21. return Optional.ofNullable(user).map(User::getUsername);
  22. }

filter()

Pass the value in Optional as a parameter. If it meets the rules, an Optional object is returned, otherwise an empty Optional object (Optional.empty) is returned.


    
    
  
  
  1. public Optional<T> filter (Predicate<? super T> predicate) {
  2. Objects.requireNonNull(predicate);
  3. if (!isPresent())
  4. return this;
  5. else
  6. return predicate.test(value) ? this : empty();
  7. }

Actual combat

ifPresent(), this is a terminal operation. If the value exists, the specified consumption method will be called.


    
    
  
  
  1. // Get the value of book, if book is null, return the default value
  2. String book = Optional.ofNullable(person).map(Person::getBook).orElse( "default");
  3. // If person is not null, print salary
  4. Optional.ofNullable(person).ifPresent(p -> System.out.println(p.getSalary()));
  5. ​// If book is null, set the default value
  6. Optional.ofNullable(person)
  7. .map(Person::getComputer)
  8. .ifPresent(c -> c.setBrandName( "default name"));
  9. Optional.ofNullable(person)
  10. .map(Person::getComputer)
  11. .ifPresent( this::consumerTest);
  12. public void consumerTest (Computer computer){
  13. System.out.println( "consumer test");
  14. System.out.println(computer);
  15. }
  16. // Get brand, if brandName is "", throw an exception
  17. // Because map can only filter out null values, and we usually need to make other judgments at work, we can use map to parse a certain attribute in the entity class, and then use filter to perform corresponding filtering.
  18. String brand = Optional.ofNullable(person)
  19. .map(Person::getComputer)
  20. .map(Computer::getBrandName)
  21. .filter(b -> !b.equals( ""))
  22. .orElseThrow(() -> new NumberFormatException ( "Brand is empty" ));
  23. System.out.println( "brand: " + brand);

Guess you like

Origin blog.csdn.net/asdf12388999/article/details/128954810