# Java 8 可选类

> 原文： [https://beginnersbook.com/2017/10/java-8-optional-class/](https://beginnersbook.com/2017/10/java-8-optional-class/)

在 Java 8 中，我们在`java.util`包中新引入了`Optional`类。引入此类是为了避免在我们的代码中不执行空检查时经常遇到的 NullPointerException。使用这个类，我们可以很容易地检查变量是否具有 null 值，通过这样做，我们可以避免 NullPointerException。在本指南中，我们将了解如何使用 Optional 类以及此类的各种方法的用法。

在我们看到 Optional 类的示例之前，让我们看看当我们不使用 Optional 类并且不执行 null 检查时会发生什么。

## Java 示例：不使用 Optional 类

在这个例子中，我们没有将值赋给 String str，我们试图从中获取[子串](https://beginnersbook.com/2013/12/java-string-substring-method-example/)。由于 str 中没有值，程序抛出 NullPointerException。

```java
public class Example {  
    public static void main(String[] args) {  
    	String[] str = new String[10];   
        //Getting the substring
        String str2 = str[9].substring(2, 5);
        //Displaying substring
        System.out.print(str2);  
    }  
}
```

输出：

```java
Exception in thread "main" java.lang.NullPointerException
at Example.main(Example.java:5)
```

## 解决方案：使用 Optional Class

Optional 类的`Optional.ofNullable()`方法，如果给定对象有值，则返回 Non-empty 可选，否则返回空 Optional。
我们可以使用`isPresent()`方法检查返回的 Optional 值是空还是非空。

```java
//Importing Optional class
import java.util.Optional; 
public class Example { 
   public static void main(String[] args) {    
      String[] str = new String[10];     
      Optional<String> isNull = Optional.ofNullable(str[9]);        
      if(isNull.isPresent()){     
         //Getting the substring           
         String str2 = str[9].substring(2, 5);          
         //Displaying substring           
         System.out.print("Substring is: "+ str2);       
      }     
      else{      
         System.out.println("Cannot get the substring from an empty string");     
      }                
      str[9] = "AgraIsCool";       
      Optional<String> isNull2 = Optional.ofNullable(str[9]);       
      if(isNull2.isPresent()){        
         //Getting the substring            
         String str2 = str[9].substring(2, 5);            
         //Displaying substring           
         System.out.print("Substring is: "+ str2);          
      }         
      else{         
         System.out.println("Cannot get the substring from an empty string");         
      }    
   }  
}
```

Output:

```java
Cannot get the substring from an empty string
Substring is: raI
```

## 示例：可选的 isPresent（）和 ifPresent（）方法

在上面的例子中，我们已经看到通过使用`isPresent()`方法，我们可以检查特定的 Optional 对象（或实例）是空还是非空。
Optional 类中还有另一种方法，只有在给定的 Optional 对象为非空时才执行，方法为`ifPresent()`。让我们看一个例子来理解差异。

```java
//Importing Optional class
import java.util.Optional;
   public class Example {  
      public static void main(String[] args) {
         //Creating Optional object from a String
         Optional<String> GOT = Optional.of("Game of Thrones");        
         //Optional.empty() creates an empty Optional object        
         Optional<String> nothing = Optional.empty();
         /* isPresent() method: Checks whether the given Optional         
          * Object is empty or not.         
          */        
         if (GOT.isPresent()) {          
            System.out.println("Watching Game of Thrones");       
         } 
         else {            
            System.out.println("I am getting Bored");      
         }
         /* ifPresent() method: It executes only if the given Optional         
          * object is non-empty.         
          */        
         //This will print as the GOT is non-empty        
         GOT.ifPresent(s -> System.out.println("Watching GOT is fun!"));                
         //This will not print as the nothing is empty        
         nothing.ifPresent(s -> System.out.println("I prefer getting bored"));
   }
}
```

Output:

```java
Watching Game of Thrones
Watching GOT is fun!
```

## Java 8 - 可选的 orElse（）和 orElseGet（）方法

如果该对象为空，则这两个方法 orElse（）和 orElseGet（）返回 Optional Object 的值，如果该对象为空，则返回作为参数传递给此方法的默认值。

```java
//Importing Optional class
import java.util.Optional;
   public class Example {  
      public static void main(String[] args) {
         //Creating Optional object from a String
         Optional<String> GOT = Optional.of("Game of Thrones");        
         //Optional.empty() creates an empty Optional object        
         Optional<String> nothing = Optional.empty();

         //orElse() method
         System.out.println(GOT.orElse("Default Value")); 
         System.out.println(nothing.orElse("Default Value")); 

         //orElseGet() method
         System.out.println(GOT.orElseGet(() -> "Default Value")); 
         System.out.println(nothing.orElseGet(() -> "Default Value")); 

    }
}
```

Output:

```java
Game of Thrones
Default Value
Game of Thrones
Default Value
```

## Java 8 - Optional.map 和 Optional.flatMap

在这个例子中，我们将看到 Optional 如何与 map 和 flatMap 一起使用。

```java
//Importing Optional class
import java.util.Optional; 
public class Example {   
   public static void main(String[] args) {
      //Creating Optional object from a String       
      Optional<String> GOT = Optional.of("Game of Thrones");       
      //Optional.empty() creates an empty Optional object       
      Optional<String> nothing = Optional.empty();
      System.out.println(GOT.map(String::toLowerCase));        
      System.out.println(nothing.map(String::toLowerCase));
      Optional<Optional<String>> anotherOptional = Optional.of(Optional.of("BreakingBad"));        
      System.out.println("Value of Optional object"+anotherOptional);        
      System.out.println("Optional.map: "             
          +anotherOptional.map(gender -> gender.map(String::toUpperCase)));        
      //Optional<Optional<String>>    -> flatMap -> Optional<String>        
      System.out.println("Optional.flatMap: "            
          +anotherOptional.flatMap(gender -> gender.map(String::toUpperCase)));
   }
}
```

Output:

```java
Optional[game of thrones]
Optional.empty
Value of Optional objectOptional[Optional[BreakingBad]]
Optional.map: Optional[Optional[BREAKINGBAD]]
Optional.flatMap: Optional[BREAKINGBAD]
```

## 示例：可选带过滤器

在这个例子中，我们将看到 Optional 如何与 filter 一起使用。要阅读有关过滤器的信息，请参阅本指南： [Java 过滤器](https://beginnersbook.com/2017/10/java-8-stream-filter/)。
**有关过滤器的更多教程：**

1.  [Java - 过滤地图](https://beginnersbook.com/2017/10/java-8-filter-a-map-by-keys-and-values/)
2.  [从 Java](https://beginnersbook.com/2017/10/java-8-filter-null-values-from-a-stream/) 中的流中过滤空值

```java
//Importing Optional class
import java.util.Optional; 
public class Example {  
   public static void main(String[] args) {
      //Creating Optional object from a String       
      Optional<String> GOT = Optional.of("Game of Thrones");              
      /* Filter returns an empty Optional instance if the output doesn't         
       * contain any value, else it returns the Optional object of the          
       * given value.         
       */        
      System.out.println(GOT.filter(s -> s.equals("GAME OF THRONES")));         
      System.out.println(GOT.filter(s -> s.equalsIgnoreCase("GAME OF THRONES")));
   }
}
```

Output:

```java
Optional.empty
Optional[Game of Thrones]
```

**参考文献：**
[Java 8 - 可选类 JavaDoc](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html)