日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【Java 8系列】Java开发者的判空利器 -- Optional

發(fā)布時間:2023/12/8 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java 8系列】Java开发者的判空利器 -- Optional 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

熱門系列:

  • 【Java 8系列】收集器Collector與工具類Collectors

  • 【Java 8系列】Stream詳解,看這一篇就夠啦

  • 【Java 8系列】Lambda 表達式,一看就廢

  • 【Java 8系列】Java日期時間的新主宰者:LocalDate、LocalTime、LocalDateTime、ZonedDateTime

  • ??程序人生,精彩搶先看


目錄

1.前序

2.正文

2.1?Optional的起源

2.2?Optional使用場景

2.2.1 為什么要用?

2.2.2 什么場景用?

2.3 常用方法使用

2.3.1 empty()

2.3.2?of()

2.3.3?ofNullable()

2.3.4?isPresent()

2.3.5?get()

2.3.6?ifPresent()

2.3.7?filter()

2.3.8?map()

2.3.9?flatMap()

2.3.10?orElse()

2.3.11?orElseGet()

2.3.12?orElseThrow()

3.總結(jié)


1.前序

JDK8是Oracle在2014年3月19日發(fā)布正式版的,和JDK7(2011年7月發(fā)布)相隔了近3年(拖的時間堪比JDK7和JDK6之間的時間,與歷史版本發(fā)布間隔相比排在第二位,JDK6發(fā)布是2006,JDK7與之相比之間差了5年,這兩個版本發(fā)布時間間隔最長,中間發(fā)生了Oracle收購SUN的大事件,JDK6因此曾成為使用率最高的JDK,),中間因意見不統(tǒng)一多次延遲。

距離現(xiàn)在已經(jīng)近6年了。但是,目前仍然有很多公司在使用此版本作為開發(fā)版本!(至少我目前所呆的公司仍在使用,各位目前常用的是哪個版本呢?歡迎留言。。。)

但是為什么現(xiàn)在才拿出來記錄呢。。。。當然是因為,我樂意啊,,哈哈。。(其實是最近有時間了,想要做一個Java 8系列的博文集啦)

最近,我會不定期,持續(xù)輸出Java 8新特性且常用的一些技術(shù)點,例如OptionalLambda表達式和函數(shù)式接口、Stream、日期時間API、重復(fù)注釋、類型推斷、?注解的擴展等等,與大家一起分享并記錄!感興趣,可以插個眼~~~!好了,今天先和大家一起扒一扒如題的判空類:Optional


2.正文

2.1?Optional的起源

著名的 NullPointerException?是引起系統(tǒng)失敗最常見的原因。很久以前Google Guava項目引入了Optional作為解決空指針異常的一種方式,不贊成代碼被null檢查的代碼污染,期望程序員寫整潔的代碼。受Google Guava的鼓勵,Optional?現(xiàn)在是Java 8庫的一部分。

Optional?只是一個容器,它可以保存一些類型的值或者null。它提供很多有用的方法,如官方文檔API所示:

修飾符和類型方法和說明
static <T>?Optional<T>empty() 返回一個空Optional實例。
booleanequals(Object?obj) 指示其他某個對象是否“等于”此Optional。
Optional<T>filter(Predicate<? super?T>?predicate) 如果存在一個值,并且該值與給定的謂詞匹配,則返回一個Optional描述值的描述,否則返回一個empty?Optional。
<U>?Optional<U>flatMap(Function<? super?T,Optional<U>>?mapper) 如果存在值,則將提供的Optional-bearing映射函數(shù)應(yīng)用于該值,返回該結(jié)果,否則返回empty?Optional。
Tget() 如果此值存在Optional,則返回該值,否則拋出NoSuchElementException。
inthashCode() 返回當前值的哈希碼值(如果有);如果沒有值,則返回0(零)。
voidifPresent(Consumer<? super?T>?consumer) 如果存在值,請使用該值調(diào)用指定的使用者,否則不執(zhí)行任何操作。
booleanisPresent() true如果存在值,則返回,否則返回false。
<U>?Optional<U>map(Function<? super?T,? extends U>?mapper) 如果存在值,則將提供的映射函數(shù)應(yīng)用于該值,如果結(jié)果為非null,則返回Optional描述結(jié)果的描述。
static <T>?Optional<T>of(T?value) 返回Optional具有指定的當前非空值的。
static <T>?Optional<T>ofNullable(T?value) 返回Optional描述指定值的描述,如果不為null,則返回null?Optional。
TorElse(T?other) 返回值(如果存在),否則返回other。
TorElseGet(Supplier<? extends?T>?other) 返回值(如果存在),否則調(diào)用other并返回該調(diào)用的結(jié)果。
<X extends?Throwable>
T
orElseThrow(Supplier<? extends X>?exceptionSupplier) 返回包含的值(如果存在),否則拋出異常,由提供的供應(yīng)商創(chuàng)建。
StringtoString() 返回此Optional的非空字符串表示形式,適用于調(diào)試。

但實際上,JDK1.8中Optional 總共有17個方法, 除去兩個私有的構(gòu)造方法, 除去equals, hashCode, toString三個方法外,;只剩下12個 Optional 提供的方法。

?

2.2?Optional使用場景

2.2.1 為什么要用?

在使用一個技術(shù)之前,我們必須要做一些思考,這樣是很有必要的!能幫我更好的做到:知其然,知其所以然;(其實說簡單點,就是防止少挖坑,騷年,醒醒吧!!你的bug還沒有修復(fù)完~~~)

先說說為什么要用!!試想一下,你的代碼或者你的小伙伴的代碼中,你是否或多或少的見過類似如下的這些代碼:

String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();//將上面的代碼進行判空處理 if (user != null) {Address address = user.getAddress();if (address != null) {Country country = address.getCountry();if (country != null) {String isocode = country.getIsocode();if (isocode != null) {isocode = isocode.toUpperCase();}}} }

尤其是,當有很大一段業(yè)務(wù)邏輯處理的時候,你會發(fā)現(xiàn),代碼不光看起來很臃腫,并且難以閱讀,可讀性很差!那如果我們調(diào)整為使用optional來編寫的話,可以轉(zhuǎn)換成如下寫法:

Optional.ofNullable(user).map(User::getAddress).map(Address::getCountry).map(Country::getIsocode).ifPresent(s-> s.toUpperCase());

如此,代碼的可讀性和整潔度,都好了許多!并且使用這種鏈式處理,也能更好的提高開發(fā)效率!這也是我們?yōu)槭裁葱枰玫?strong>optional的原因啦!

2.2.2 什么場景用?

我們寫代碼,在保證業(yè)務(wù)功能的正確和穩(wěn)定性的基礎(chǔ)之上,才會去考慮代碼的可讀性與簡潔度,而不是一味的追求形式!!否則只會是華而不實,不僅容易出錯,更是本末倒置!

個人總結(jié)了幾點如下:

  • 當使用值為空的情況,并非源于報錯時產(chǎn)生,可以使用Optional(因為有錯誤的情況,肯定是不正常的,需要處理的)

  • 對于一個對象,我們需要做判空、過濾、某些校驗的時候,可以使用Optional

?

2.3 常用方法使用

方法介紹順序,從簡單的開始:

2.3.1 empty()

empty 方法返回一個不包含值的 Optional 實例, 注意不保證返回的 empty 是單例, 不要用 == 比較。

public static<T> Optional<T> empty();

?

2.3.2?of()

返回一個 Optional 實例;代表指定的非空值, 如果傳入 null 會立刻拋出空指針異常。

public static <T> Optional<T> of(T value);

?

2.3.3?ofNullable()

  • 返回一個 Optional 實例, 如果指定非空值則實例包含非空值, 如果傳入 null 返回不包含值的 empty
  • public static <T> Optional<T> ofNullable(T value);

    ?

    2.3.4?isPresent()

    isPresent 用來判斷實例是否包含值, 如果不包含非空值返回 false, 否則返回 true

    public boolean isPresent();

    ?

    2.3.5?get()

    get 方法, 如果實例包含值則返回當前值, 否則拋出 NoSushElementException 異常

    public T get();

    ?

    2.3.6?ifPresent()

    ifPresent 方法作用是當實例包含值時, 來執(zhí)行傳入的 Consumer, 比如調(diào)用一些其他方法

    public void ifPresent(Consumer<? super T> consumer);

    例如如下用法:

    public void testIfPresent() {// ifPresent 表示 Optional 中的對象存在才會執(zhí)行 Consumer 接口對象中的方法List<String> dataList = new ArrayList<>();// 1. 不為空沒有值的集合Optional.ofNullable(dataList).ifPresent(t -> {System.out.println("1"); // 輸出 1t.forEach(a -> System.out.println(a));}); }

    ?

    2.3.7?filter()

    filter 方法用于過濾不符合條件的值, 接收一個 Predicate 參數(shù), 如果符合條件返回代表值的 Optional 實例, 否則返回 empty;例如:

    private static List<User> userList = new ArrayList<>();/*** 初始化 user 集合*/ @Before public void initEveryTestBefore() {userList.add(new User(22, "王旭", "wang.xu","123456", '1', true));userList.add(new User(21, "孫萍", "sun.ping","a123456", '2', false));userList.add(new User(23, "步傳宇", "bu.zhuan.yu", "b123456", '1', false));userList.add(new User(18, "蔡明浩", "cai.ming.hao","c123456", '1', true));userList.add(new User(17, "郭林杰", "guo.lin.jie", "d123456", '1', false));userList.add(new User(29, "韓凱", "han.kai", "e123456", '1', true));userList.add(new User(22, "韓天琪", "han.tian.qi","f123456", '2', false));userList.add(new User(21, "郝瑋", "hao.wei","g123456", '2', false));userList.add(new User(19, "胡亞強", "hu.ya.qing","h123456", '1', false));userList.add(new User(14, "季愷", "ji.kai","i123456", '1', false));userList.add(new User(17, "荊帥", "jing.shuai","j123456", '1', true));userList.add(new User(16, "姜有琪", "jiang.you.qi","k123456", '1', false));logger.info("initEveryTestBefore, size {}", userList.size()); }// filter: optional 中的對象在不為空,并且滿足某個條件的時候才會返回 @Test public void testFilter() {// 1. 在集合中有年齡大于 18 歲的才會返回所有對象Optional.ofNullable(userList).filter(t -> t.stream().anyMatch(u -> u.getAge() > 18)).ifPresent(t -> {t.forEach(u -> {System.out.println("1:" + u.toString());});});// 2. 因為集合中沒有年齡大于 50 歲的,因此不會返回任何對象Optional.ofNullable(userList).filter(t -> t.stream().anyMatch(u -> u.getAge() > 50)).ifPresent(t -> {t.forEach(u -> {System.out.println("2:" + u.toString());});}); }

    ?

    2.3.8?map()

    map 方法是鏈式調(diào)用避免空指針的核心方法, 當實例包含值時, 對值執(zhí)行傳入的 Function 邏輯, 并返回一個代表結(jié)果值的新的 Optional 實例;也就是將 optional 中的對象轉(zhuǎn)成 其他對象,或者修改對象中的屬性;如:

    // 1. 返回 optional 中的對象年齡在 18 歲以上的 Optional.ofNullable(userList).map(t -> {List<User> tempList = new ArrayList<>();t.forEach(u -> {if (u.getAge() > 18) {tempList.add(u);}});return tempList;}).ifPresent(t -> {t.forEach(u -> {System.out.println("1:" + u.toString());});});

    ?

    2.3.9?flatMap()

    flatMap方法是將 optional 中的對象轉(zhuǎn)成 optional 對象,或者修改對象中的屬性;與map方法類似。不同之處在于:

    Optional.ofNullable(userList).map(t -> {List<User> tempList = new ArrayList<>();t.forEach(u -> {if (u.getAge() > 18) {tempList.add(u);}});//不同之處return Optional.of(tempList);})

    ?

    2.3.10?orElse()

    orElse方法是如果實例包含值, 那么返回這個值, 否則返回指定的默認值, 如null

    public T orElse(T other);

    ?

    2.3.11?orElseGet()

    orElseGet方法是如果實例包含值, 返回這個值;否則,它會執(zhí)行作為參數(shù)傳入的?Supplier(供應(yīng)者)?函數(shù)式接口,并將返回其執(zhí)行結(jié)果。

    public T orElseGet(Supplier<? extends T> other);

    orElse與orElseGet不同之處:

    public void givenPresentValue_whenCompare_thenOk() {User user = new User("john@gmail.com", "1234");logger.info("Using orElse");User result = Optional.ofNullable(user).orElse(createNewUser());logger.info("Using orElseGet");User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser()); }

    輸出結(jié)果:

    Using orElse Creating New User Using orElseGet

    ?

    2.3.12?orElseThrow()

    如果實例不包含值, 調(diào)用傳入的 Supplier 參數(shù), 生成一個異常實例并拋出.這個方法通常與全局異常處理器一起使用, 當參數(shù)或者其他情況獲取不到值時, 拋出自定義異常, 由異常處理器處理成通用返回結(jié)果, 返回給前端;如:

    Optional.ofNullable(tempList).orElseThrow(() -> runtimeException).forEach(t -> System.out.println("2:" + t));

    3.總結(jié)

    以上即為JDK1.8新增的Optional類的常用方法及場景記錄!舉例的代碼方面,比較零散,但主要是為了方便大家有一個功能使用和方法差別上的了解!(所以,不要在意那些雞零狗碎的代碼意義~~~~)

    路漫漫,其修遠兮!歡迎大家提問、留言!!!

    ?

    微信同款:https://mp.weixin.qq.com/s/jhJBI6uK6bvCBTUxnj-LUA

    總結(jié)

    以上是生活随笔為你收集整理的【Java 8系列】Java开发者的判空利器 -- Optional的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。