一、空指针问题与Optional的引入
需求:根据人获取他买的车保险名字。
Person:
1 package com.cy.java8; 2 3 import lombok.Data; 4 5 @Data 6 public class Person { 7 8 private Car car; 9 }
Car:
1 package com.cy.java8; 2 3 import lombok.Data; 4 5 @Data 6 public class Car { 7 8 private Insurance insurance; 9 }
Insurance:
1 package com.cy.java8; 2 3 import lombok.Data; 4 5 @Data 6 public class Insurance { 7 8 private String name; 9 }
1 package com.cy.java8; 2 3 public class NullPointerException { 4 5 public static void main(String[] args) { 6 String insuracneName = getInsuranceName(new Person()); 7 8 } 9 10 /** 11 * 根据Person获取保险的名字,直接这么写肯定抛空指针异常 12 */ 13 private static String getInsuranceName(Person person){ 14 return person.getCar().getInsurance().getName(); 15 } 16 17 /** 18 * 于是加上非空判断 19 * 如果嵌套比较深,这种判断比较麻烦,代码可读性很差 20 */ 21 private static String getInsuranceName2(Person person){ 22 if(null != person){ 23 Car car = person.getCar(); 24 if(null != car){ 25 Insurance insurance = car.getInsurance(); 26 if(null != insurance){ 27 return insurance.getName(); 28 } 29 } 30 } 31 return "UNKNOWN"; 32 } 33 34 /** 35 * 使用多个return语句来避免上面的这种嵌套 36 * 看起来是清晰了一些,但是还是很啰嗦 37 */ 38 private static String getInsuranceName3(Person person){ 39 final String defaultValue = "UNKNOWN"; 40 if(null == person){ 41 return defaultValue; 42 } 43 44 Car car = person.getCar(); 45 if(null == car){ 46 return defaultValue; 47 } 48 49 Insurance insurance = car.getInsurance(); 50 if(null == insurance){ 51 return defaultValue; 52 } 53 54 return insurance.getName(); 55 } 56 57 /** 58 * 使用Optional解决上面的问题 59 */ 60 61 }
二、Optional的api介绍
解决上面的问题之前,先介绍下Optional的API
of
empty
ofNullable
get
orElse
orElseGet
orElseThrow
isPresent ifPresent
代码举例:
1 package com.cy.java8; 2 3 import java.util.Optional; 4 5 public class OptionalUsage { 6 7 public static void main(String[] args) { 8 //创建一个空的Optional 9 Optional<Insurance> optional = Optional.empty(); 10 11 //根据insurance作为value创建optional,如果insurance为null,报空指针 12 Insurance insurance = new Insurance(); 13 Optional<Insurance> optional1 = Optional.of(insurance); 14 15 //对前面两个的综合,如果insurance为null,返回empty 16 Optional<Insurance> optional2 = Optional.ofNullable(null); 17 18 //orElseGet:如果有值则返回,没有值则返回elseGet括号里的,括号里是Suppiler 19 optional2.orElseGet(Insurance::new); 20 21 optional2.orElse(new Insurance()); 22 23 //optional2.orElseThrow(() -> new RuntimeException("Not have a value")); 24 25 /** 26 * filter 27 */ 28 Insurance insurance1 = optional1.filter(i -> i.getName() == null).get(); 29 System.out.println(insurance1); 30 31 /** 32 * map 33 */ 34 Optional<String> nameOptional = optional1.map(i -> i.getName()); 35 String s = nameOptional.orElse("empty value"); 36 System.out.println(s); 37 38 /** 39 * isPresent ifPresent 40 */ 41 Insurance insurance3 = new Insurance(); 42 insurance3.setName("xiao wang"); 43 Optional<Insurance> optional3 = Optional.of(insurance3); 44 Optional<String> nameOptional3 = optional3.filter(i -> i.getName().equals("xiao wang")).map(i -> i.getName()); 45 System.out.println(nameOptional3.isPresent()); 46 nameOptional3.ifPresent(i -> System.out.println("insurance name is :" + i)); 47 48 /** 49 * optional判断空写法 50 */ 51 System.out.println(getInsuranceName(null)); 52 System.out.println(getInsuranceNameByOptional(null)); 53 } 54 55 private static String getInsuranceName(Insurance insurance){ 56 if(null == insurance){ 57 return "unknown"; 58 } 59 return insurance.getName(); 60 } 61 62 private static String getInsuranceNameByOptional(Insurance insurance){ 63 return Optional.ofNullable(insurance).map(Insurance::getName).orElse("unknown"); 64 } 65 }
打印结果:
Insurance(name=null) empty value true insurance name is :xiao wang unknown unknown
三、使用Optional解决上面的判空问题
需要改写Person、Car
Person:
1 package com.cy.java8; 2 3 import lombok.Data; 4 5 import java.util.Optional; 6 7 @Data 8 public class Person { 9 private Optional<Car> car = Optional.empty(); 10 }
Car:
1 package com.cy.java8; 2 3 import lombok.Data; 4 5 import java.util.Optional; 6 7 @Data 8 public class Car { 9 10 private Optional<Insurance> insurance = Optional.empty(); 11 }
Insurance:
1 package com.cy.java8; 2 3 import lombok.Data; 4 5 @Data 6 public class Insurance { 7 8 private String name; 9 }
1 package com.cy.java8; 2 3 import java.util.Optional; 4 5 public class OptionalInAction { 6 7 public static void main(String[] args) { 8 System.out.println(getInsuranceNameByOptional(null)); 9 System.out.println(getInsuranceNameByOptional(new Person())); 10 } 11 12 private static String getInsuranceNameByOptional(Person person) { 13 String insuranceName = Optional.ofNullable(person) 14 .flatMap((p) -> p.getCar()) 15 .flatMap(c -> c.getInsurance()) 16 .map(i -> i.getName()).orElse("unknown"); 17 return insuranceName; 18 } 19 20 }
打印如下:
unknown unknown
----