JDK8中引入的Optional類可以解決空指針異常, 讓我們省略繁瑣的非空判斷。
Optional類就是一個可以為null容器, 或者保存指定類型的數據,或者為null。
static <T> Optional<T> | empty() 返回一個空的Optional對象 |
boolean | equals(Object obj) |
Optional<T> | filter(Predicate<? super T> predicate) 如果有值,返回符合predicate條件的Optional對象, 否則返回空的Optional對象 |
<U> Optional<U> | flatMap(Function<? super T,Optional<U>> mapper) 如果有值,執行mapper映射函數,返回Optional對象, 如果沒有值返回空的Optional對象 |
T | get() 如果值存在返回, 如果不存在拋出異常NoSuchElementException. |
int | hashCode() |
void | ifPresent(Consumer<? super T> consumer) 如果值存在就執行consumer函數,否則什么也不做 |
boolean | isPresent() 判斷值是否存在 |
<U> Optional<U> | map(Function<? super T,? extends U> mapper) 如果值存在就執行mapper映射函數, |
static <T> Optional<T> | of(T value) 把指定的value值封裝為Optional對象,如果value為null,產生空指針異常 |
static <T> Optional<T> | ofNullable(T value) 把指定的value值封裝為Optional對象,如果value為null返回一個空的Optional對象 |
T | orElse(T other) 如果值存在就返回,如果不存在返回other |
T | orElseGet(Supplier<? extends T> other) 如果存在就返回值,如果不存在,執行Supplier返回另外一個值 |
<X extends Throwable> T | orElseThrow(Supplier<? extends X> exceptionSupplier) 如果存在就返回該值,如果不存在拋出由exceptionSupplier生成的異常 |
String | toString() |
package com.wkcto.optional;
import java.util.Optional;
/**
* 演示Optional的基本操作
* Author : 動力節點老崔
*/
public class Test01 {
public static void main(String[] args) {
//1)把一個字符串封裝為Optional對象
Optional<String> ofString = Optional.of("wkcto"); //參數不能為null
//2)為指定的值創建Optional對象,如果參數為null,返回空的Optional對象
Optional<String> ofString2 = Optional.ofNullable(null); //參數可以為null
System.out.println(ofString2); //Optional.empty
//3)直接創建一個空的Optional對象
Optional<String> ofString3 = Optional.empty();
System.out.println( ofString3 );
//4)get() 獲得Optional對象中的值,如果值不存在會產生異常
String text = ofString.get();
System.out.println(text); //wkcto
// text = ofString2.get(); //java.util.NoSuchElementException
//5)orElse(),如果Optional對象中有值就返回,沒有則返回指定的其他值
text = ofString.orElse("another");
System.out.println( text ); //wkcto
text = ofString2.orElse("another");
System.out.println( text ); //another
//6)orElseGet(),如果有值就返回,如果Optional對象中沒值則創建一個新的
text = ofString2.orElseGet(() -> "newString");
System.out.println( text ); //newString
//7)orElseThrow(),如果值存在就返回,否則拋出異常
// text = ofString2.orElseThrow(NullPointerException::new);
text = ofString.orElseThrow(NullPointerException::new);
System.out.println( text );
//8)filter(),如果Optional對象有值返回滿足指定條件的Optional對象, 否則返回空的Optional對象
text = ofString.filter(s -> s.length() > 10).orElse("lenth is letter than 10");
System.out.println( text );
text = ofString.filter(s -> s.length() > 3).orElse("lenth is letter than 3");
System.out.println( text );
//9) map() 如果Optional對象的值存在,執行mapper映射函數
text = ofString.map(x -> x.toUpperCase()).orElse("Failure");
System.out.println( text ); //WKCTO
text = ofString2.map(x -> x.toUpperCase()).orElse("Failure");
System.out.println( text ); //Failure
//10)ifPresent() 如果Optional對象有值就執行Consumer函數
ofString.ifPresent(s -> System.out.println("處理數據" + s));
ofString2.ifPresent(s -> System.out.println("處理數據" + s)); //沒有值什么也不做
System.out.println("optional");
}
}
Optional示例1
package com.wkcto.optional;
import javax.print.attribute.standard.NumberUp;
import javax.sound.midi.Soundbank;
import java.util.Optional;
/**
* Optional練習1
* Author : 動力節點老崔
*/
public class Test02 {
public static void main(String[] args) {
Address address = new Address("Beijing", "大族企業灣");
// User user = new User("laocui", address);
// User user = new User();
User user = null;
System.out.println( getName1(user));
System.out.println( getName2(user));
System.out.println( getCity1(user));
System.out.println( getCity2(user));
}
//定義方法返回指定用戶的用戶名 ,如果用戶名不存在返回unknown
public static String getName1( User user){
if ( user == null ){ //判斷參數接收的User對象是否為null
return "unknown";
}
return user.name;
}
//Optional可以解決空指針問題
public static String getName2(User user){
return Optional.ofNullable(user) //把參數接收的user對象包裝為Optional對象
.map(u -> u.name) //映射,只需要用戶名
.orElse("unknown"); //存在就返回,不存在返回unknown
}
//定義方法返回指定用戶的城市
public static String getCity1(User user){
if ( user != null){
if (user.address != null){
return user.address.city;
}
}
return "unkown";
}
//使用Optional返回用戶的城市
public static String getCity2(User user){
return Optional.ofNullable(user) //把參數對象包裝為Optional對象
.map(u -> u.address) //映射用戶的地址
.map(addr -> addr.city) //映射地址的城市
.orElse("Unkown"); //有就返回,沒有返回Unknown
}
}
//定義用戶類
class User{
String name;
Address address;
public User(String name, Address address) {
this.name = name;
this.address = address;
}
public User() {
}
}
//定義地址類
class Address{
String city;
String house;
public Address(String city, String house) {
this.city = city;
this.house = house;
}
}
Optional在實際開發中的應用
package com.wkcto.optionalapp2;
import java.util.Optional;
/**
* 每個人可能有一部車,每輛車可能都有保險,每個保險公司都有自己的名稱
* Author : 動力節點老崔
*/
public class Test {
public static void main(String[] args) {
//1)創建保險對象
Insurance in1 = new Insurance();
in1.setName("pingan");
Optional<Insurance> insurance1 = Optional.ofNullable(in1); //有保險
Optional<Insurance> insurance2 = Optional.ofNullable(null); //保險為null
//2)創建小汽車對象
Car car1 = new Car("Geely", insurance1); //Geely汽車有保險
Car car2 = new Car("Haval", insurance2); //Haval汽車沒有保險
Optional<Car> carOptional1 = Optional.ofNullable(car1); //車有保險
Optional<Car> carOptional2 = Optional.ofNullable(car2); //車無保險
Optional<Car> carOptional3 = Optional.ofNullable(null) ; //沒有車
//3)創建Person對象
Person p1 = new Person("lisi", carOptional1); //lisi有車,有保險
Person p2 = new Person("wangwu", carOptional2); //wangwu,有車,沒有保險
Person p3 = new Person("zhaoliu", carOptional3); //zhaoliu, 沒有車
//4)使用Optional包裝Person對象
Optional<Person> person1 = Optional.ofNullable(p1); //有車,有保險
Optional<Person> person2 = Optional.ofNullable(p2); //有車,沒有保險
Optional<Person> person3 = Optional.ofNullable(p3); //沒有車
//5)獲得人的汽車品牌
System.out.println( person1.map(Person::getCar)); //返回一個Optional<Optional<Car>>類型的數據
System.out.println( person1.flatMap(Person::getCar)); //Optional<Car>
System.out.println( person1.flatMap(Person::getCar).map(Car::getBrand).orElse("Unknown"));
System.out.println( person2.flatMap(Person::getCar).map(Car::getBrand).orElse("Unknown"));
System.out.println( person3.flatMap(Person::getCar).map(Car::getBrand).orElse("Unknown"));
//6)獲得人的汽車的保險的名稱
System.out.println( person1.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
.orElse("Unknwon"));
System.out.println( person2.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
.orElse("Unknwon"));
System.out.println( person3.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
.orElse("Unknwon"));
}
}
package com.wkcto.optionalapp2;
import java.util.Optional;
/**
* 定義人類
* Author : 動力節點老崔
*/
public class Person {
private String name;
private Optional<Car> car; //不確定是否有車
public Person(String name, Optional<Car> car) {
this.name = name;
this.car = car;
}
public String getName() {
return name;
}
public Person setName(String name) {
this.name = name;
return this;
}
public Optional<Car> getCar() {
return car;
}
public Person setCar(Optional<Car> car) {
this.car = car;
return this;
}
}
package com.wkcto.optionalapp2;
import java.util.Optional;
/**
* 汽車類
* Author : 動力節點老崔
*/
public class Car {
private String brand; //汽車品牌
private Optional<Insurance> insurance; //不能確定每輛汽車都有保險
public Car(String brand, Optional<Insurance> insurance) {
this.brand = brand;
this.insurance = insurance;
}
public String getBrand() {
return brand;
}
public Car setBrand(String brand) {
this.brand = brand;
return this;
}
public Optional<Insurance> getInsurance() {
return insurance;
}
public Car setInsurance(Optional<Insurance> insurance) {
this.insurance = insurance;
return this;
}
}
package com.wkcto.optionalapp2;
/**
* 保險類
* Author : 動力節點老崔
*/
public class Insurance {
private String name;
public String getName() {
return name;
}
public Insurance setName(String name) {
this.name = name;
return this;
}
}