亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java新特性之Optional類超詳細介紹

 更新時間:2023年07月25日 09:54:45   作者:栗箏i  
這篇文章主要給大家介紹了關(guān)于Java新特性之Optional類超詳細介紹的相關(guān)資料,Java8中的Optional類是一個容器對象,可以包含null或非null值,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下

前言

Optional 類是 Java 8 才引入的,Optional 是個容器,它可以保存類型 T 的值,或者僅僅保存 null。Optional 提供了很多方法,這樣我們就不用顯式進行空值檢測。Optional 類的引入很好的解決空指針異常。

Java 8 引入 Optional 類,用來解決 NullPointerException。 Optional 代替 if…else 解決空指針問題,使代碼更加簡潔。

1、Optional類概述

1.1、Optional類介紹

Optional 類是 Java 8 才引入的,Optional 是個容器,它可以保存類型 T 的值,或者僅僅保存 null。Optional 提供了很多方法,這樣我們就不用顯式進行空值檢測。Optional 類的引入很好的解決空指針異常。

Java 8 引入 Optional 類,用來解決 NullPointerException。 Optional 代替 if…else 解決空指針問題,使代碼更加簡潔。

1.2、Java8之前的空指針異常判斷

Java 在使用對象過程中,訪問任何方法或?qū)傩远伎赡軐?dǎo)致 NullPointerException:

例如我們通過以下方法,獲取存在 student 對象中的 Age 值。

        public String getIsocode (Student student){
            return student.getAge();
        }

在這樣的示例中,如果我們想要避免由 studentstudent.age 為空而導(dǎo)致的空指針問題,我們就需要采用防御式檢查減少 NullPointerException(在訪問每一個值之前對其進行明確地檢查):

       public String getIsocode (Student student){
            if (null == student) {
                // doSomething
                return "Unknown";
            }
            if (null = student.getAge()) {
                // doSomething
                return "Unknown";
            }
            return student.getAge();
        }

然而,這種方案并不是很理想,因為為此會多出多個不同的退出點(return),使得代碼維護變得艱難,之后每個可能的 null 檢查都會新增一個退出點。

為了簡化這個過程,我們來看看用 Optional 類是怎么做的。

1.3、Java8之后Optional的使用

當需要判斷的量多時,此時的這些判斷語句可能會導(dǎo)致代碼臃腫冗余,為此 Java8 特意推出了 Optional 類來幫助我們?nèi)ヌ幚砜罩羔槷惓!?/p>

下面是 Optional 的一些基本用法:

@Data
public class Student {
    private Integer age;
}
---
public class Test {
    public static void main(String[] args) {
        // 假設(shè) student 這個對象從數(shù)據(jù)庫中查出的
        Student student = getStudent();
        // 創(chuàng)建一個可接受 null 的 Optiona l類
        Optional<Student> optional = Optional.ofNullable(student);
        // 用法1:獲取 student 對象中的某個值,如果不存在的話則取默認值(不具有短路作用)
        Integer a1 = optional.map(Student::getAge).orElse(20));
        // 用法2:獲取 student 對象中的某個值,如果不存在的話則取默認值(具有短路作用,因為是懶加載)
        Integer a2 = optional.map(Student::getAge).orElseGet(() -> Integer.MAX_VALUE);
      	// 用法3:判斷對象是否存在,不存在則拋出異常
        optional.orElseThrow(() -> new RuntimeException("student不存在!"));
      	// 用法4:判斷對象是否存在,存在的話對對象進行操作,例如給對象賦初始值
        optional.ifPresent(o -> o.setAge(18));
      	// 用法5:對象存在時,且年齡滿足一定條件容器才會繼續(xù)保存這對象,否則將會剔除
        optional.filter(o -> o.getAge() > 10);
    }
}

2、Optional類使用

2.1、Optional類常用方法總結(jié)

方法描述
empty返回一個空的 Optional 實例
filter如果值存在并且滿足提供的謂詞,就返回包含該值的 Optional 對象;否則返回一個空的 Optional 對象
flatMap如果值存在,就對該值執(zhí)行提供的 mapping 函數(shù)調(diào)用,返回一個 Optional 類型的值,否則就返回一個空的 Optional 對象
get如果該值存在,將該值用 Optional 封裝返回,否則拋出一個 NoSuchElementException 異常
ifPresent如果值存在,就執(zhí)行使用該值的方法調(diào)用,否則什么也不做
isPresent如果值存在就返回 true,否則返回 false
map如果值存在,就對該值執(zhí)行提供的mapping 函數(shù)調(diào)用
of將指定值用 Optional 封裝之后返回,如果該值為 null,則拋出一個 NullPointerException 異常
ofNullable將指定值用 Optional 封裝之后返回,如果該值為 null,則返回一個空的 Optional 對象
orElse如果有值則將其返回,否則返回一個默認值
orElseGet如果有值則將其返回,否則返回一個由指定的 Supplier 接口生成的值
orElseThrow如果有值則將其返回,否則拋出一個由指定的 Supplier 接口生成的異常

2.2、Optional對象創(chuàng)建

2.2.1、Optional.empty()方法

使用 Optional.empty() 方法聲明一個空的 Optional:

// 通過靜態(tài)工廠方法 Optional.empty(),創(chuàng)建一個空的 Optional 對象
Optional<Student> optStudent = Optional.empty();

2.2.2、Optional.of(T t)方法

使用 Optional.of(T t) 方法創(chuàng)建一個包含非空值的 Optional 對象 (不推薦):

// 靜態(tài)工廠方法 Optional.of(T t),依據(jù)一個非空值創(chuàng)建一個 Optional 對象
Optional<Student> optStudent = Optional.of(student);

如果 student 為 null,這段代碼會立即拋出一個 NullPointerException,而不是等到訪問 student 的屬性值時才返回一個錯誤。

2.2.3、Optional.ofNullable(T t)方法

使用 Optional.ofNullable(T t) 方法創(chuàng)建一個包含可能為空的值的 Optional 對象 (推薦):

// 用靜態(tài)工廠方法 Optional.ofNullable(T t),你可以創(chuàng)建一個允許 null 值的 Optional 對象
Optional<Student> optStudent = Optional.ofNullable(student);

2.3、Optional對象獲取

2.3.1、get()方法

get() 方法,如果變量存在,它直接返回封裝的變量值,否則就拋出一個 NoSuchElementException 異常,不推薦使用:

optional.map(Student::getAge).get()

2.3.2、orElse(T other)方法

orElse(T other) 方法,它允許你在 Optional 對象不包含值時提供一個默認值:

optional.map(Student::getAge).orElse(20));

2.3.3、orElseGet(Supplier<? extends T> other)方法

orElseGet(Supplier<? extends T> other) 方法,它是 orElse 方法的延遲調(diào)用版,Supplier 方法只有在 Optional 對象不含值時才執(zhí)行調(diào)用(懶加載):

optional.map(Student::getAge).orElseGet(() -> Integer.MAX_VALUE);

2.3.4、orElseThrow(Supplier<? extends X> exceptionSupplier)方法

orElseThrow(Supplier<? extends X> exceptionSupplier) 方法,它和 get 方法非常類似,它們遭遇 Optional 對象為空時都會拋出一個異常,但是使用 orElseThrow 可以定制希望拋出的異常類型:

optional.orElseThrow(() -> new RuntimeException("student不存在!"));

2.3.5、ifPresent(Consumer<? super T> consumer)方法

ifPresent(Consumer<? super T> consumer) 方法,它讓能在變量值存在時執(zhí)行一個作為參數(shù)傳入的方法,否則就不進行任何操作:

optional.ifPresent(o -> o.setAge(18));

2.4、Optional對象中值的提取和轉(zhuǎn)換

2.4.1、map()方法

map() 方法,如果值存在,就對該值執(zhí)行提供的 mapping 函數(shù)調(diào)用,如果值不存在,則返回一個空的 Optional 對象。

引入 Optional 以前:

String name = null;
    if(insurance != null){
        name = insurance.getName();
    }

引入 Optional 以后:

Optional<String> name = Optional.ofNullable(insurance).map(Insurance::getName);

Optional 的 map 方法和 Java 8 中 Stream 的 map 方法相差無幾。

2.4.2、flatMap()方法

flatMap() 方法,對于嵌套式的 Optiona 結(jié)構(gòu),我們應(yīng)該使用 flatMap 方法,將兩層的 Optional 合并成一個。

我們試著重構(gòu)以下代碼:

  public String getCarInsuranceName(Person person) {
      return person.getCar().getInsurance().getName();
  }

由于我們剛剛學習了如何使用 map,我們的第一反應(yīng)可能是我們可以利用 map 重寫之前的代碼:

  Optional<Person> optPerson = Optional.of(person);
      Optional<String> name =
          optPerson.map(Person::getCar)
                   .map(Car::getInsurance)
                   .map(Insurance::getName);

不幸的是,這段代碼無法通過編譯。為什么呢? optPerson 是 Optional<Person> 類型的 變量, 調(diào)用 map 方法應(yīng)該沒有問題。但 getCar 返回的是一個 Optional<Car> 類型的對象,這意味著 map 操作的結(jié)果是一個 Optional<Optional<Car>> 類型的對象。因此,它對 getInsurance 的調(diào)用是非法的。

下面應(yīng)用 map 和 flatMap 對上述示例進行重寫:

  public String getCarInsuranceName(Optional<Person> person) { 
      return person.flatMap(Person::getCar)
                       .flatMap(Car::getInsurance)
                       .map(Insurance::getName)
                       .orElse("Unknown"); // 如果Optional的結(jié)果 值為空設(shè)置默認值
  }

2.5、Optional對象其他方法

2.5.1、isPresent()方法

可以使用 isPresent() 方法檢查 Optional 對象是否包含非空值,例如:

Optional<String> optional = Optional.of("Hello World"); 
if (optional.isPresent()) { 
    System.out.println(optional.get()); 
}

2.5.2、filter()方法

filter() 方法接受一個謂詞作為參數(shù)。如果 Optional 對象的值存在,并且它符合謂詞的條件,filter 方法就返回其值,否則它就返回一個空的 Optional 對象。

比如,你可能需要檢查保險公司的名稱是否為 “Cambridge-Insurance”。

Insurance insurance = ...;
	if(insurance != null && "CambridgeInsurance".equals(insurance.getName())){
			System.out.println("ok");
  }

使用 Optional 對象的 filter 方法,這段代碼可以重構(gòu)如下:

Optional<Insurance> optInsurance = ...;
optInsurance.filter(insurance -> "CambridgeInsurance".equals(insurance.getName()))
            .ifPresent(x -> System.out.println("ok"));

3、Optional注意事項

3.1、Optional的序列化問題

由于 Optiona l類設(shè)計時就沒特別考慮將其作為類的字段使用,所以它也并未實現(xiàn) Serializable 接口。由于這個原因,如果你的應(yīng)用使用了某些要求序列化的庫或者框架,在域模型中使用Optional,有可能引發(fā)應(yīng)用程序故障。

然而,我們相信,通過前面的介紹,我們已經(jīng)看到用 Optional 聲明域模型中的某些類型是個不錯的主意,尤其是你需要遍歷有可能全部或部分為空,或者可能不存在的對象時。如果你一定要實現(xiàn)序列化的域模型,作為替代方案, 我們建議你像下面這個例子那樣,提供一個能訪問聲明為 Optional、變量值可能缺失的接口,代碼清單如下:

public class Person {
    private Car car;
    public Optional<Car> getCarAsOptional() {
      return Optional.ofNullable(car);
    } 
}

3.2、避免使用基礎(chǔ)類型的 Optional 對象

Optional 提供了的一些基礎(chǔ)類型 —— OptionalInt、OptionalLong 以及 OptionalDouble ,但不推薦大家使用基礎(chǔ)類型的 Optional,因為基礎(chǔ)類型的 Optional 不支持 map、 flatMap 以及 filter 方法,而這些卻是 Optional 類常用的方法??梢允褂?Optional<Int>Optional<Long>, Optional<Double> 等替代。3. orElse方法的使用

3.3、orElse方法的使用

orElse 中調(diào)用的方法一直都會被執(zhí)行,orElseGet 方法只有在 Optional 對象不含值時才會被調(diào)用,所以使用 orElse 方法時需要謹慎, 以免誤執(zhí)行某些不被預(yù)期的操作。此種情況下,可使用 orElseGet 方法代替它。

總結(jié)

到此這篇關(guān)于Java新特性之Optional類超詳細介紹的文章就介紹到這了,更多相關(guān)Java新特性O(shè)ptional類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論