一、空指針問題與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
----