Java 8 引入的一個很有趣的特性是 Optional 類。Optional 類主要解決的問題是臭名昭著的空指針異常(NullPointerException)。
合理使用Optional可以很好避免 NullPointerException
加入存在如下對象:
@Data
public class Competition {
private String name;
private String gender;
private int score;
private Result result;
@Data
public static class Result{
private String last;
private String space;
private Champion champion;
@Data
public static class Champion{
private String pion;
private String str;
}
}
}
1、基礎用法
如果我們要獲取Champion對象中的str的值,爲避免空指針我們可能需要寫以下代碼:
Competition competition = new Competition();
competition.setGender("男");
competition.setName("Test");
competition.setScore(92);
Competition.Result result = new Competition.Result();
result.setLast("last");
result.setSpace("pace");
Competition.Result.Champion champion = new Competition.Result.Champion();
champion.setPion("pion");
champion.setStr("buffer");
competition.setResult(result);
result.setChampion(champion);
String str = "";
if(competition != null){
Competition.Result result1 = competition.getResult();
if(result1 != null){
Competition.Result.Champion champion1 = result1.getChampion();
if(champion1 != null){
str = champion1.getStr();
}
}
}
System.out.println("結果:" + str);
如果對象中嵌套的對象太多,我們可能需要寫更多層的if判斷,就爲了一個字段的判斷,代碼寫很多行,代碼量多不說,也容易視覺疲勞。如果使用Optional類,我們可以將代碼優化爲如下:
public static void main(String[] args) {
Competition competition =new Competition();
competition.setGender("男");
competition.setName("Test");
competition.setScore(92);
Competition.Result result =new Competition.Result();
result.setLast("last");
result.setSpace("pace");
Competition.Result.Champion champion = new Competition.Result.Champion();
champion.setPion("pion");
champion.setStr("buffer");
competition.setResult(result);
result.setChampion(champion);
// 以下代碼,只要存在空指針(result對象空指針或champion對象空指針)均會執行orElse代碼,輸出空字符串
System.out.println(
Optional.ofNullable(competition)
.map(t -> t.getResult())
.map(Competition.Result::getChampion)
.map(s-> s.getStr())
.orElse(""));
}
//如果我們不想要默認值,可以拋出異常,使用orElseThrow方法
//可以將t理解爲對象,即對象實例competition
System.out.println(
Optional.ofNullable(competition)
.map(t -> t.getResult())
.map(Competition.Result::getChampion)
.map(s -> s.getStr())
// .orElse(""));
.orElseThrow(() ->new IllegalArgumentException("Error")));
2、filter數據過濾
filter方法檢查給定的Option值是否滿足某些條件,如果滿足則返回同一個Option實例,否則返回空Optional
Optional<String> name = Optional.of("michael");
Optional<String> longName = name.filter((value) -> value.length() > 6);
//我們可以通過以下代碼輸出filter方法的結果:
System.out.println(longName.orElse("The name is less than 6 characters"));
System.out.println(longName.get());
代碼:
package com.code.study.example.optional;
import lombok.Data;
/**
* @author: Mwl
* @date: 2020/4/5 5:12 下午
**/
@Data
public class Competition {
private String name;
private String gender;
private int score;
private Result result;
@Data
public static class Result{
private String last;
private String space;
private Champion champion;
@Data
public static class Champion{
private String pion;
private String str;
}
}
}
package com.code.study.example.optional;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum OperateContentEnum {
/**
* 操作類型
*/
CREATE_BILL("生成對賬單", "系統自動觸發", null),
USE_OFFSET_AMOUNT("付款單已使用抵消金額", "系統自動觸發", "抵消金額:{0}");
private String operateRecord; //操作記錄
private String operatorName; //操作人
private String remark; //備註
}
package com.code.study.example.optional;
import java.text.MessageFormat;
import java.util.Optional;
/**
* @author: Mwl
* @date: 2020/4/5 5:16 下午
**/
public class Main {
//格式化
public static String buildLogDo(OperateContentEnum contentEnum, String extraString){
String str = Optional.ofNullable(extraString)
.map(s -> MessageFormat.format(contentEnum.getRemark(), s))
.orElse(contentEnum.getRemark());
//這裏s 理解爲就是extraString,如果extraString爲對象,s就是對象的實例,字符串就是其本身
return str;
}
public static void main(String[] args) {
Competition competition =new Competition();
competition.setGender("男");
competition.setName("Test");
competition.setScore(92);
Competition.Result result =new Competition.Result();
result.setLast("last");
result.setSpace("pace");
Competition.Result.Champion champion = new Competition.Result.Champion();
champion.setPion("pion");
champion.setStr("buffer");
competition.setResult(result);
result.setChampion(champion);
System.out.println(
Optional.ofNullable(competition)
.map(t -> t.getResult())
.map(Competition.Result::getChampion)
.map(s -> s.getStr())
// .orElse(""));
.orElseThrow(() ->new IllegalArgumentException("Error")));
System.out.println("=======================");
System.out.println(buildLogDo(OperateContentEnum.USE_OFFSET_AMOUNT, "lalla"));
System.out.println("=======================");
Optional<String> name = Optional.of("michael");
Optional<String> longName = name.filter((value) -> value.length() > 6);
System.out.println(longName.orElse("The name is less than 6 characters"));
System.out.println("=======================");
System.out.println(longName.get());
System.out.println("=======================");
Optional<Competition> user = Optional.ofNullable(competition);
System.out.println(user.get().getName());
}
}