---
title: Java 8 Optionalæä½³æåï¼ä¼é
è§£å³ç©ºæé
shortTitle: Optionalæä½³æå
category:
- Javaæ ¸å¿
tag:
- Javaæ°ç¹æ§
description: æ¬æè¯¦ç»ä»ç»äºJava 8å¼å
¥çOptionalç±»ï¼éè¿°äºOptionalç设计åè¡·åç¨æ³ãéè¿å®é
ç代ç 示ä¾ï¼å±ç¤ºäºå¦ä½ä½¿ç¨Optionalæ¥ä¼é
å°è§£å³ç©ºæéé®é¢ï¼é¿å
ç¨åºä¸çNullPointerExceptionãææ¡Optionalçä½¿ç¨æ¹æ³ï¼è®©æ¨çJavaä»£ç æ´å å¥å£®åå¯é ã
head:
- - meta
- name: keywords
content: Java,Java SE,Javaåºç¡,Javaæç¨,äºå¥çJavaè¿é¶ä¹è·¯,Javaè¿é¶ä¹è·¯,Javaå
¥é¨,æç¨,java8,Optional,java Optional,空æéå¼å¸¸, NullPointerException
---
æ³å¦ä¹ ï¼æ°¸è¿é½ä¸æï¼å°¤å
¶æ¯é对 Java 8 éé¢ç好ä¸è¥¿ï¼Optional å°±æ¯å
¶ä¸ä¹ä¸ï¼è¯¥ç±»æä¾äºä¸ç§ç¨äºè¡¨ç¤ºå¯éå¼èé空å¼ç¨ç类级å«è§£å³æ¹æ¡ãä½ä¸ºä¸å Java ç¨åºåï¼æççæ¯ç¦éäº [NullPointerExceptionï¼NPEï¼](https://javabetter.cn/exception/npe.html)ï¼å°½ç®¡åå®çå¾å°±åä¸ä½èæåï¼ç¥éå®ä¹æ¯è¿«ä¸å¾å·²ââç¨åºæ£å¨ä½¿ç¨ä¸ä¸ªå¯¹è±¡å´åç°è¿ä¸ªå¯¹è±¡çå¼ä¸º nullï¼äºæ¯ Java èææºå°±æåå²å 尿宿äºåºæ¥å½åæ¿ç½ªç¾ã
å½ç¶äºï¼æä»¬ç¨åºåæ¯å¯æè´£ä»»å¿çï¼ä¸ä¼åè§ä¸ç®¡ï¼äºæ¯å°±æäºå¤§éç null 弿£æ¥ãå°½ç®¡ææ¶åè¿ç§æ£æ¥å®å
¨æ²¡æå¿
è¦ï¼ä½æä»¬å·²ç»ä¹ æ¯äºä¾è¡å
¬äºãç»äºï¼Java 8 çä¸ä¸å»äºï¼å°±å¼å
¥äº Optionalï¼ä»¥ä¾¿æä»¬ç¼åç代ç ä¸åé£ä¹å»èåæ¿ã

### 01ãæ²¡æ Optional 伿ä»ä¹é®é¢
æä»¬æ¥æ¨¡æä¸ä¸ªå®é
çåºç¨åºæ¯ãå°ç第ä¸å¤©ä¸çï¼é¢å¯¼è马就ç»ä»å®æäºä¸ä¸ªä»»å¡ï¼è¦ä»ä»æ°æ®åºä¸æ ¹æ®ä¼å ID æåä¸ä¸ªä¼åçå§åï¼ç¶åå°å§åæå°å°æ§å¶å°ãè½ç¶æ¯æ°æ¥çï¼ä½è¿ä¸ªä»»å¡é¾ä¸åå°çï¼äºæ¯ä»è±äº 10 åéåä¸äºè¿æ®µä»£ç ï¼
```java
public class WithoutOptionalDemo {
class Member {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static void main(String[] args) {
Member mem = getMemberByIdFromDB();
if (mem != null) {
System.out.println(mem.getName());
}
}
public static Member getMemberByIdFromDB() {
// å½å ID çä¼åä¸åå¨
return null;
}
}
```
ç±äºå½å ID çä¼åä¸åå¨ï¼æä»¥ `getMemberByIdFromDB()` æ¹æ³è¿åäº null æ¥ä½ä¸ºæ²¡æè·åå°è¯¥ä¼åçç»æï¼é£å°±æå³ç卿å°ä¼åå§åçæ¶åè¦å
对 mem å¤ç©ºï¼å¦åå°±ä¼æåº NPE å¼å¸¸ï¼ä¸ä¿¡ï¼è®©å°çæ `if (mem != null)` 廿è¯è¯ï¼æ§å¶å°ç«é©¬æå°éè¯¯å æ ç»ä½ é¢è²ççã
```
Exception in thread "main" java.lang.NullPointerException
at com.cmower.dzone.optional.WithoutOptionalDemo.main(WithoutOptionalDemo.java:24)
```
### 02ãOptional æ¯å¦ä½è§£å³è¿ä¸ªé®é¢ç
å°çæä»£ç æäº¤åï¼å°±å
´é«éçå°å»æ¾èé©¬è¦æ°çä»»å¡äºãæ¬çèå¿å¦ä¹ çæåº¦ï¼å°ç请æ±è马çä¸ä¸èªå·±ç代ç ï¼äºæ¯èçå°±åè¯ä»åºè¯¥å°è¯ä¸ä¸ Optionalï¼å¯ä»¥é¿å
没æå¿
è¦ç null 弿£æ¥ãç°å¨ï¼è®©æä»¬æ¥ççå°çæ¯å¦ä½éè¿ Optional æ¥è§£å³ä¸è¿°é®é¢çã
```java
public class OptionalDemo {
public static void main(String[] args) {
Optional optional = getMemberByIdFromDB();
optional.ifPresent(mem -> {
System.out.println("ä¼åå§åæ¯ï¼" + mem.getName());
});
}
public static Optional getMemberByIdFromDB() {
boolean hasName = true;
if (hasName) {
return Optional.of(new Member("æ²é»çäº"));
}
return Optional.empty();
}
}
class Member {
private String name;
public String getName() {
return name;
}
// getter / setter
}
```
`getMemberByIdFromDB()` æ¹æ³è¿åäº `Optional` ä½ä¸ºç»æï¼è¿æ ·å°±è¡¨æ Member å¯è½åå¨ï¼ä¹å¯è½ä¸åå¨ï¼è¿æ¶åå°±å¯ä»¥å¨ Optional ç `ifPresent()` æ¹æ³ä¸ä½¿ç¨ Lambda è¡¨è¾¾å¼æ¥ç´æ¥æå°ç»æã
Optional 乿以å¯ä»¥è§£å³ NPE çé®é¢ï¼æ¯å ä¸ºå®æç¡®çåè¯æä»¬ï¼ä¸éè¦å¯¹å®è¿è¡å¤ç©ºãå®å°±å¥½åååè·¯å£çè·¯æ ï¼æç¡®å°åè¯ä½ 该å¾åªèµ°ã
### 03ãå建 Optional 对象
1ï¼å¯ä»¥ä½¿ç¨éææ¹æ³ `empty()` å建ä¸ä¸ªç©ºç Optional 对象
```java
Optional empty = Optional.empty();
System.out.println(empty); // è¾åºï¼Optional.empty
```
2ï¼å¯ä»¥ä½¿ç¨éææ¹æ³ `of()` å建ä¸ä¸ªé空ç Optional 对象
```java
Optional opt = Optional.of("æ²é»çäº");
System.out.println(opt); // è¾åºï¼Optional[æ²é»çäº]
```
å½ç¶äºï¼ä¼ éç» `of()` æ¹æ³çåæ°å¿
é¡»æ¯é空çï¼ä¹å°±æ¯è¯´ä¸è½ä¸º nullï¼å¦åä»ç¶ä¼æåº NullPointerExceptionã
```java
String name = null;
Optional optnull = Optional.of(name);
```
3ï¼å¯ä»¥ä½¿ç¨éææ¹æ³ `ofNullable()` å建ä¸ä¸ªå³å¯ç©ºåå¯é空ç Optional 对象
```java
String name = null;
Optional optOrNull = Optional.ofNullable(name);
System.out.println(optOrNull); // è¾åºï¼Optional.empty
```
`ofNullable()` æ¹æ³å
鍿ä¸ä¸ªä¸å
表达å¼ï¼å¦æä¸ºåæ°ä¸º nullï¼åè¿åç§æå¸¸é EMPTYï¼å¦åä½¿ç¨ new å
³é®åå建äºä¸ä¸ªæ°ç Optional 对象ââä¸ä¼åæåº NPE å¼å¸¸äºã
### 04ã夿弿¯å¦åå¨
å¯ä»¥éè¿æ¹æ³ `isPresent()` 夿ä¸ä¸ª Optional 对象æ¯å¦åå¨ï¼å¦æåå¨ï¼è¯¥æ¹æ³è¿å trueï¼å¦åè¿å falseââåä»£äº `obj != null` ç夿ã
```java
Optional opt = Optional.of("æ²é»çäº");
System.out.println(opt.isPresent()); // è¾åºï¼true
Optional optOrNull = Optional.ofNullable(null);
System.out.println(optOrNull.isPresent()); // è¾åºï¼false
```
Java 11 åè¿å¯ä»¥éè¿æ¹æ³ `isEmpty()` å¤æä¸ `isPresent()` ç¸åçç»æã
```java
Optional opt = Optional.of("æ²é»çäº");
System.out.println(opt.isEmpty()); // è¾åºï¼false
Optional optOrNull = Optional.ofNullable(null);
System.out.println(optOrNull.isEmpty()); // è¾åºï¼true
```
### 05ãé空表达å¼
Optional ç±»æä¸ä¸ªé常ç°ä»£åçæ¹æ³ââ`ifPresent()`ï¼å
许æä»¬ä½¿ç¨å½æ°å¼ç¼ç¨çæ¹å¼æ§è¡ä¸äºä»£ç ï¼å æ¤ï¼ææå®ç§°ä¸ºé空表达å¼ãå¦ææ²¡æè¯¥æ¹æ³çè¯ï¼æä»¬é常éè¦å
éè¿ `isPresent()` æ¹æ³å¯¹ Optional 对象è¿è¡å¤ç©ºååæ§è¡ç¸åºç代ç ï¼
```java
Optional optOrNull = Optional.ofNullable(null);
if (optOrNull.isPresent()) {
System.out.println(optOrNull.get().length());
}
```
æäº `ifPresent()` ä¹åï¼æ
åµå°±å®å
¨ä¸åäºï¼å¯ä»¥ç´æ¥å° Lambda 表达å¼ä¼ éç»è¯¥æ¹æ³ï¼ä»£ç æ´å ç®æ´ï¼æ´å ç´è§ã
```java
Optional opt = Optional.of("æ²é»çäº");
opt.ifPresent(str -> System.out.println(str.length()));
```
Java 9 åè¿å¯ä»¥éè¿æ¹æ³ `ifPresentOrElse(action, emptyAction)` æ§è¡ä¸¤ç§ç»æï¼éç©ºæ¶æ§è¡ actionï¼ç©ºæ¶æ§è¡ emptyActionã
```java
Optional opt = Optional.of("æ²é»çäº");
opt.ifPresentOrElse(str -> System.out.println(str.length()), () -> System.out.println("为空"));
```
### 06ã设置ï¼è·åï¼é»è®¤å¼
ææ¶åï¼æä»¬å¨å建ï¼è·åï¼ Optional å¯¹è±¡çæ¶åï¼éè¦ä¸ä¸ªé»è®¤å¼ï¼`orElse()` å `orElseGet()` æ¹æ³å°±æ´¾ä¸ç¨åºäºã
`orElse()` æ¹æ³ç¨äºè¿åå
è£¹å¨ Optional 对象ä¸çå¼ï¼å¦æè¯¥å¼ä¸ä¸º nullï¼åè¿åï¼å¦åè¿åé»è®¤å¼ãè¯¥æ¹æ³çåæ°ç±»ååå¼çç±»åä¸è´ã
```java
String nullName = null;
String name = Optional.ofNullable(nullName).orElse("æ²é»çäº");
System.out.println(name); // è¾åºï¼æ²é»çäº
```
`orElseGet()` æ¹æ³ä¸ `orElse()` æ¹æ³ç±»ä¼¼ï¼ä½åæ°ç±»åä¸åã妿 Optional 对象ä¸çå¼ä¸º nullï¼åæ§è¡åæ°ä¸ç彿°ã
```java
String nullName = null;
String name = Optional.ofNullable(nullName).orElseGet(()->"æ²é»çäº");
System.out.println(name); // è¾åºï¼æ²é»çäº
```
ä»è¾åºç»æä»¥å代ç çå½¢å¼ä¸æ¥çï¼è¿ä¸¤ä¸ªæ¹æ³æå
¶ç¸ä¼¼ï¼è¿ä¸å
å¼èµ·æä»¬çæçï¼Java ç±»åºç设计è
æå¿
è¦è¿æ ·ååï¼
å设ç°å¨æè¿æ ·ä¸ä¸ªè·åé»è®¤å¼çæ¹æ³ï¼å¾ä¼ ç»çæ¹å¼ã
```java
public static String getDefaultValue() {
System.out.println("getDefaultValue");
return "æ²é»çäº";
}
```
ç¶åï¼éè¿ `orElse()` æ¹æ³å `orElseGet()` æ¹æ³åå«è°ç¨ `getDefaultValue()` æ¹æ³è¿åé»è®¤å¼ã
```java
public static void main(String[] args) {
String name = null;
System.out.println("orElse");
String name2 = Optional.ofNullable(name).orElse(getDefaultValue());
System.out.println("orElseGet");
String name3 = Optional.ofNullable(name).orElseGet(OrElseOptionalDemo::getDefaultValue);
}
```
注ï¼`ç±»å :: æ¹æ³å`æ¯ Java 8 å¼å
¥çè¯æ³ï¼æ¹æ³åå颿¯æ²¡æ `()` çï¼è¡¨æè¯¥æ¹æ³å¹¶ä¸ä¸å®ä¼è¢«è°ç¨ã
è¾åºç»æå¦ä¸æç¤ºï¼
```java
orElse
getDefaultValue
orElseGet
getDefaultValue
```
è¾åºç»ææ¯ç¸ä¼¼çï¼æ²¡ä»ä¹å¤ªå¤§çä¸åï¼è¿æ¯å¨ Optional 对象çå¼ä¸º null çæ
åµä¸ãåå¦ Optional 对象çå¼ä¸ä¸º null å¢ï¼
```java
public static void main(String[] args) {
String name = "æ²é»çä¸";
System.out.println("orElse");
String name2 = Optional.ofNullable(name).orElse(getDefaultValue());
System.out.println("orElseGet");
String name3 = Optional.ofNullable(name).orElseGet(OrElseOptionalDemo::getDefaultValue);
}
```
è¾åºç»æå¦ä¸æç¤ºï¼
```java
orElse
getDefaultValue
orElseGet
```
å¦ï¼`orElseGet()` 没æå»è°ç¨ `getDefaultValue()`ãåªä¸ªæ¹æ³çæ§è½æ´ä½³ï¼ä½ æç½äºå§ï¼
### 07ãè·åå¼
ç´è§ä»è¯ä¹ä¸æ¥çï¼`get()` æ¹æ³ææ¯ææ£å®çè·å Optional 对象å¼çæ¹æ³ï¼ä½å¾éæ¾ï¼è¯¥æ¹æ³æ¯æç¼ºé·çï¼å 为åå¦ Optional 对象çå¼ä¸º nullï¼è¯¥æ¹æ³ä¼æåº NoSuchElementException å¼å¸¸ãè¿å®å
¨ä¸æä»¬ä½¿ç¨ Optional ç±»çåè¡·ç¸æã
```java
public class GetOptionalDemo {
public static void main(String[] args) {
String name = null;
Optional optOrNull = Optional.ofNullable(name);
System.out.println(optOrNull.get());
}
}
```
è¿æ®µç¨åºå¨è¿è¡æ¶ä¼æåºå¼å¸¸ï¼
```
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:141)
at com.cmower.dzone.optional.GetOptionalDemo.main(GetOptionalDemo.java:9)
```
尽管æåºçå¼å¸¸æ¯ NoSuchElementException è䏿¯ NPEï¼ä½å¨æä»¬çæ¥ï¼æ¾ç¶æ¯å¨âäºåæ¥ç¬ç¾æ¥âã建议 `orElseGet()` æ¹æ³è·å Optional 对象çå¼ã
### 08ãè¿æ»¤å¼
å°çéè¿ Optional 类对ä¹åç代ç è¿è¡äºå级ï¼å®æååå
´é«éçå°è·å»æ¾è马è¦ä»»å¡äºãè马è§å¾è¿å°ä¼åä¸éï¼å¤´èçµæ´»ï¼å干活积æï¼å¾å¼å¾å¹å
»ï¼å°±å交ç»äºå°çä¸ä¸ªæ°çä»»å¡ï¼ç¨æ·æ³¨åæ¶å¯¹å¯ç çé¿åº¦è¿è¡æ£æ¥ã
å°çæ¿å°ä»»å¡åï¼ä¹å¼äºè±ï¼å 为ä»åè¦å¦ä¹ Optional ç±»ç `filter()` æ¹æ³ï¼è¿å°±æ´¾ä¸äºç¨åºã
```java
public class FilterOptionalDemo {
public static void main(String[] args) {
String password = "12345";
Optional opt = Optional.ofNullable(password);
System.out.println(opt.filter(pwd -> pwd.length() > 6).isPresent());
}
}
```
`filter()` æ¹æ³çåæ°ç±»å为 Predicateï¼Java 8 æ°å¢çä¸ä¸ªå½æ°å¼æ¥å£ï¼ï¼ä¹å°±æ¯è¯´å¯ä»¥å°ä¸ä¸ª Lambda 表达å¼ä¼ éç»è¯¥æ¹æ³ä½ä¸ºæ¡ä»¶ï¼å¦æè¡¨è¾¾å¼çç»æä¸º falseï¼åè¿åä¸ä¸ª EMPTY ç Optional 对象ï¼å¦åè¿åè¿æ»¤åç Optional 对象ã
å¨ä¸ä¾ä¸ï¼ç±äº password çé¿åº¦ä¸º 5 ï¼æä»¥ç¨åºè¾åºçç»æä¸º falseãå设å¯ç çé¿åº¦è¦æ±å¨ 6 å° 10 ä½ä¹é´ï¼é£ä¹è¿å¯ä»¥å追å ä¸ä¸ªæ¡ä»¶ãæ¥çå°çå¢å é¾åº¦åç代ç ã
```java
Predicate len6 = pwd -> pwd.length() > 6;
Predicate len10 = pwd -> pwd.length() < 10;
password = "1234567";
opt = Optional.ofNullable(password);
boolean result = opt.filter(len6.and(len10)).isPresent();
System.out.println(result);
```
è¿æ¬¡ç¨åºè¾åºçç»æä¸º trueï¼å 为å¯ç åæäº 7 ä½ï¼å¨ 6 å° 10 ä½ä¹é´ãæ³è±¡ä¸ä¸ï¼åå¦å°çä½¿ç¨ if-else æ¥å®æè¿ä¸ªä»»å¡ï¼ä»£ç 该æå¤åé¿ã
### 09ã转æ¢å¼
å°çæ£æ¥å®äºå¯ç çé¿åº¦ï¼ä»ç¶è§å¾ä¸å¤å°½å
´ï¼è§å¾è¦å¯¹å¯ç ç强度ä¹è¿è¡æ£æ¥ï¼æ¯å¦è¯´å¯ç ä¸è½æ¯âpasswordâï¼è¿æ ·çå¯ç 太弱äºãäºæ¯ä»åå¼å§ç ç©¶èµ·äº `map()` æ¹æ³ï¼è¯¥æ¹æ³å¯ä»¥æç
§ä¸å®çè§åå°åæ Optional 对象转æ¢ä¸ºä¸ä¸ªæ°ç Optional 对象ï¼åæç Optional 对象ä¸ä¼æ´æ¹ã
å
æ¥çå°çåçä¸ä¸ªç®åçä¾åï¼
```java
public class OptionalMapDemo {
public static void main(String[] args) {
String name = "æ²é»çäº";
Optional nameOptional = Optional.of(name);
Optional intOpt = nameOptional
.map(String::length);
System.out.println( intOpt.orElse(0));
}
}
```
å¨ä¸é¢è¿ä¸ªä¾åä¸ï¼`map()` æ¹æ³çåæ° `String::length`ï¼æå³çè¦ å°åæçå符串类åç Optional æç
§å符串é¿åº¦éæ°çæä¸ä¸ªæ°ç Optional 对象ï¼ç±»å为 Integerã
ææ¸
æ¥äº `map()` æ¹æ³çåºæ¬ç¨æ³åï¼å°çå³å®æ `map()` æ¹æ³ä¸ `filter()` æ¹æ³ç»åèµ·æ¥ç¨ï¼åè
ç¨äºå°å¯ç 转å为å°åï¼åè
ç¨äºå¤æé¿åº¦ä»¥åæ¯å¦æ¯âpasswordâã
```java
public class OptionalMapFilterDemo {
public static void main(String[] args) {
String password = "password";
Optional opt = Optional.ofNullable(password);
Predicate len6 = pwd -> pwd.length() > 6;
Predicate len10 = pwd -> pwd.length() < 10;
Predicate eq = pwd -> pwd.equals("password");
boolean result = opt.map(String::toLowerCase).filter(len6.and(len10 ).and(eq)).isPresent();
System.out.println(result);
}
}
```

好äºï¼æäº²ç±ç读è
æåï¼ä»¥ä¸å°±æ¯æ¬æçå
¨é¨å
容äºââå¯ä»¥è¯´æ¯å²ä¸æä½³ Optional æåäºï¼è½çå°è¿éç齿¯æä¼ç§çç¨åºåï¼äºå¥å¿
é¡»è¦ä¼¸åºå¤§ææä¸ºä½ ç¹ä¸ªèµã
----
GitHub 䏿 æ 17000+ ç弿ºç¥è¯åºã[äºå¥ç Java è¿é¶ä¹è·¯](https://github.com/itwanger/toBeBetterJavaer)ã第ä¸ç PDF ç»äºæ¥äºï¼å
æ¬Javaåºç¡è¯æ³ãæ°ç»&å符串ãOOPãéåæ¡æ¶ãJava IOãå¼å¸¸å¤çãJava æ°ç¹æ§ãç½ç»ç¼ç¨ãNIOãå¹¶åç¼ç¨ãJVMççï¼å
±è®¡ 32 ä¸ä½åï¼500+å¼ æç»å¾ï¼å¯ä»¥è¯´æ¯éä¿ææãé£è¶£å¹½é»â¦â¦è¯¦æ
æ³ï¼[太èµäºï¼GitHub 䏿 æ 17000+ ç Java æç¨](https://javabetter.cn/overview/)
微信æ **æ²é»çäº** ææ«æä¸æ¹äºç»´ç å
³æ³¨äºå¥çååå
¬ä¼å·æ²é»çäºï¼åå¤ **222** å³å¯å
è´¹é¢åã
