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());
}
}