电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Java中Optional的使用指南

瀏覽:27日期:2022-08-17 13:55:11

提到NullPointerException(簡稱NPE)異常,相信每個Java開發人員都不陌生,從接觸編程的第1天起,它就和我們如影隨形,最近處理的線上bug中,有不少都是對象沒判空導致的NullPointerException異常。

1. 簡單回顧

引起NullPointerException異常的地方有很多,比如調用String的trim()方法,比如對BigDecimal進行計算時,比如將包裝類型轉化為基本類型時,這里簡單回顧下。

假設有個導入模版定義如下:

package com.zwwhnly.springbootaction.model;import lombok.AllArgsConstructor;import lombok.Data;/** * 導入模版 */@Data@AllArgsConstructorpublic class ImportTemplate { /** * 模版id */ private int templateId; /** * 模版名稱 */ private String templateName; /** * 模版下載url */ private String url; /** * 備注 */ private String remark;}

然后看下如下代碼:

public static void main(String[] args) { ImportTemplate importTemplate = getImportTemplateById(1); System.out.println(importTemplate.getUrl());}public static ImportTemplate getImportTemplateById(int id) { return new ImportTemplate(1, '銷售訂單-普通商品導入模版', 'o_w-140e3c1f41c94f238196539558e25bf7', null);}

正常情況下,這段代碼肯定是沒有問題的,但當getImportTemplateById方法返回null時,這段代碼就會拋出NullPointerException異常,如下所示:

public static ImportTemplate getImportTemplateById(int id) { return null;}

Java中Optional的使用指南

為了程序能正常運行,就要判斷importTemplate是否為null,所以代碼就修改為了:

public static void main(String[] args) { ImportTemplate importTemplate = getImportTemplateById(1); if (importTemplate != null) { System.out.println(importTemplate.getUrl()); }}

項目中類似的判空代碼應該有很多,大家可以自行看下自己項目的代碼。

2. 使用Optional

為了避免NullPointerException異常,JDK1.8新增了Optional類來處理空指針異常,該類位于java.util包下,提供了一系列方法,

并且可以配合Lambda表達式一起使用,使代碼看起來更加清晰,接下來我們看下它的使用方法。

2.1 創建實例

創建Optional實例有以下3種方式,分別為:

調用empty方法

Optional<ImportTemplate> optionalImportTemplate = Optional.empty();

調用of方法

ImportTemplate importTemplate = new ImportTemplate(1, '銷售訂單-普通商品導入模版', 'o_w-140e3c1f41c94f238196539558e25bf7', null);Optional<ImportTemplate> optionalImportTemplate = Optional.of(importTemplate);

調用ofNullable方法(推薦)

ImportTemplate importTemplate = new ImportTemplate(1, '銷售訂單-普通商品導入模版', 'o_w-140e3c1f41c94f238196539558e25bf7', null);Optional<ImportTemplate> optionalImportTemplate = Optional.ofNullable(importTemplate);

值得注意的是,當參數為null時,調用of方法會拋NullPointerException異常,但調用ofNullable方法不會(更符合使用場景),因此推薦使用ofNullable方法:

ImportTemplate importTemplate = null;Optional<ImportTemplate> optionalImportTemplate = Optional.of(importTemplate);

Java中Optional的使用指南

2.2 判斷是否有值

可以調用isPresent方法來判斷對象是否有值(不為null),使用方法如下所示:

ImportTemplate importTemplate = null;Optional<ImportTemplate> optionalImportTemplate = Optional.ofNullable(importTemplate);System.out.println(optionalImportTemplate.isPresent());

以上代碼的輸出結果為:

Java中Optional的使用指南

ImportTemplate importTemplate = new ImportTemplate(1, '銷售訂單-普通商品導入模版', 'o_w-140e3c1f41c94f238196539558e25bf7', null);Optional<ImportTemplate> optionalImportTemplate = Optional.ofNullable(importTemplate);System.out.println(optionalImportTemplate.isPresent());

以上代碼的輸出結果為:

Java中Optional的使用指南

看下isPresent的源碼,邏輯非常簡單,就是判斷了我們傳入的對象是否有值,即不為null:

/** * Return {@code true} if there is a value present, otherwise {@code false}. * * @return {@code true} if there is a value present, otherwise {@code false} */public boolean isPresent() { return value != null;}

2.3 獲取值

可以調用get方法來獲取對象的有值,使用方法如下所示:

ImportTemplate importTemplate = new ImportTemplate(1, '銷售訂單-普通商品導入模版', 'o_w-140e3c1f41c94f238196539558e25bf7', null);Optional<ImportTemplate> optionalImportTemplate = Optional.ofNullable(importTemplate);System.out.println(optionalImportTemplate.get());

以上代碼的輸出結果為:

Java中Optional的使用指南

值得注意的是,當我們傳入的對象為null時,調用get方法會拋出java.util.NoSuchElementException異常,而不是返回null。

ImportTemplate importTemplate = null;Optional<ImportTemplate> optionalImportTemplate = Optional.ofNullable(importTemplate);System.out.println(optionalImportTemplate.get());

以上代碼的輸出結果為:

Java中Optional的使用指南

看下get方法的源碼,就可以知道原因:

public T get() { if (value == null) { throw new NoSuchElementException('No value present'); } return value;}

2.4 先用isPresent,再用get(不推薦)

然后我們回顧下文初的代碼:

ImportTemplate importTemplate = getImportTemplateById(1);if (importTemplate != null) { System.out.println(importTemplate.getUrl());}

可能很多同學會把代碼優化為下面這樣的寫法:

Optional<ImportTemplate> optionalImportTemplate = Optional.ofNullable(getImportTemplateById(1));if (optionalImportTemplate.isPresent()) { System.out.println(optionalImportTemplate.get().getUrl());}

不推薦這么使用,因為判斷的地方沒減少,而且還不如原來看起來清晰。

2.5 ifPresent(推薦)

那該怎么優化呢?答案就是使用ifPresent方法,該方法接收一個Consumer類型的參數,當值不為null時,就執行,當值為null時,就不執行,源碼如下所示:

public void ifPresent(Consumer<? super T> consumer) { if (value != null) consumer.accept(value);}

優化之后的代碼如下所示:

Optional<ImportTemplate> optionalImportTemplate = Optional.ofNullable(getImportTemplateById(1));optionalImportTemplate.ifPresent(importTemplate -> System.out.println(importTemplate.getUrl()));

當然,也可以寫更多的邏輯:

Optional<ImportTemplate> optionalImportTemplate = Optional.ofNullable(getImportTemplateById(1));optionalImportTemplate.ifPresent(importTemplate -> { System.out.println(importTemplate.getTemplateId()); System.out.println(importTemplate.getTemplateName()); System.out.println(importTemplate.getUrl()); System.out.println(importTemplate.getRemark());});

2.6 自定義默認值

Optional類提供了以下2個方法來自定義默認值,用于當對象為null時,返回自定義的對象:

orElse orElseGet

先來看下orElse方法的使用:

public static void main(String[] args) { ImportTemplate importTemplate = null; ImportTemplate firstImportTemplate = Optional.ofNullable(importTemplate) .orElse(getDefaultTemplate()); System.out.println(firstImportTemplate); importTemplate = new ImportTemplate(2, '銷售訂單-不定規格商品導入模版', 'o_w-a7109db89f8d4508b4c6202889a1a2c1', null); ImportTemplate secondImportTemplate = Optional.ofNullable(importTemplate) .orElse(getDefaultTemplate()); System.out.println(secondImportTemplate);}public static ImportTemplate getDefaultTemplate() { System.out.println('getDefaultTemplate'); return new ImportTemplate(1, '銷售訂單-普通商品導入模版', 'o_w-140e3c1f41c94f238196539558e25bf7', null);}

輸出結果:

Java中Optional的使用指南

再來看下orElseGet方法的使用:

public static void main(String[] args) { ImportTemplate importTemplate = null; ImportTemplate firstImportTemplate = Optional.ofNullable(importTemplate) .orElseGet(() -> getDefaultTemplate()); System.out.println(firstImportTemplate); importTemplate = new ImportTemplate(2, '銷售訂單-不定規格商品導入模版', 'o_w-a7109db89f8d4508b4c6202889a1a2c1', null); ImportTemplate secondImportTemplate = Optional.ofNullable(importTemplate) .orElseGet(() -> getDefaultTemplate()); System.out.println(secondImportTemplate);}public static ImportTemplate getDefaultTemplate() { System.out.println('getDefaultTemplate'); return new ImportTemplate(1, '銷售訂單-普通商品導入模版', 'o_w-140e3c1f41c94f238196539558e25bf7', null);}

輸出結果:

Java中Optional的使用指南

從輸出結果看,2個方法好像差不多,第1次調用都返回了默認模版,第2次調用都返回了傳入的模版,但其實仔細觀察,你會發現當使用

orElse方法時,getDefaultTemplate方法執行了2次,但調用orElseGet方法時,getDefaultTemplate方法只執行了2次(只在第1次傳入模版為null時執行了)。

為什么會這樣呢?帶著這個疑問,我們看下這2個方法的源碼,其中orElse方法的源碼如下所示:

public T orElse(T other) { return value != null ? value : other;}

可以看到,參數other是個對象,這個參數肯定是要傳的,但只有value為空時,才會用到(返回)這個對象。

orElseGet方法的源碼如下所示:

public T orElseGet(Supplier<? extends T> other) { return value != null ? value : other.get();}

可以看到,參數other并不是直接傳入對象,如果value為null,才會執行傳入的參數獲取對象,如果不為null,直接返回value。

2.7 自定義異常

Optional類提供了orElseThrow方法,用于當傳入的對象為null時,拋出自定義的異常,使用方法如下所示:

public static void main(String[] args) { ImportTemplate importTemplate = new ImportTemplate(2, '銷售訂單-不定規格商品導入模版', 'o_w-a7109db89f8d4508b4c6202889a1a2c1', null); ImportTemplate firstImportTemplate = Optional.ofNullable(importTemplate) .orElseThrow(() -> new IndexOutOfBoundsException()); System.out.println(firstImportTemplate); importTemplate = null; ImportTemplate secondImportTemplate = Optional.ofNullable(importTemplate) .orElseThrow(() -> new IndexOutOfBoundsException()); System.out.println(secondImportTemplate);}

輸出結果:

Java中Optional的使用指南

2.8 過濾數據

Optional類提供了filter方法來過濾數據,該方法接收一個Predicate參數,返回匹配條件的數據,如果不匹配條件,返回一個空的Optional,使用方法如下所示:

public static void main(String[] args) { ImportTemplate importTemplate = getImportTemplateById(1); Optional<ImportTemplate> filterById = Optional.ofNullable(importTemplate) .filter(f -> f.getTemplateId() == 1); System.out.println(filterById.isPresent()); Optional<ImportTemplate> filterByName = Optional.ofNullable(importTemplate) .filter(f -> f.getTemplateName().contains('發貨單')); System.out.println(filterByName.isPresent());}public static ImportTemplate getImportTemplateById(int id) { return new ImportTemplate(1, '銷售訂單-普通商品導入模版', 'o_w-140e3c1f41c94f238196539558e25bf7', null);}

輸出結果:

Java中Optional的使用指南

2.9 轉換值

Optional類提供了以下2個方法來轉換值:

map flatMap

map方法的使用方法如下所示:

public static void main(String[] args) { ImportTemplate importTemplate = getImportTemplateById(1); Optional<String> optionalUrl = Optional.ofNullable(importTemplate) .map(f -> 'url:' + f.getUrl()); System.out.println(optionalUrl.isPresent()); System.out.println(optionalUrl.get());}public static ImportTemplate getImportTemplateById(int id) { return new ImportTemplate(1, '銷售訂單-普通商品導入模版', 'o_w-140e3c1f41c94f238196539558e25bf7', null);}

輸出結果:

Java中Optional的使用指南

flatMap方法和map方法類似,不過它支持傳入Optional,使用方法如下所示:

public static void main(String[] args) { ImportTemplate importTemplate = getImportTemplateById(1); Optional<String> optionalUrl = Optional.ofNullable(importTemplate) .flatMap(f -> Optional.ofNullable(f.getUrl())); System.out.println(optionalUrl.isPresent()); System.out.println(optionalUrl.get());}public static ImportTemplate getImportTemplateById(int id) { return new ImportTemplate(1, '銷售訂單-普通商品導入模版', 'o_w-140e3c1f41c94f238196539558e25bf7', null);}

輸出結果:

Java中Optional的使用指南

3. 總結

對于程序員來說,一不注意就會出現NullPointerException異常,避免它的方式也很簡單,比如使用前判斷不能為空:

public static void main(String[] args) { ImportTemplate importTemplate = getImportTemplateById(1); if (importTemplate != null) { System.out.println(importTemplate.getUrl()); }}

比如為空時,直接返回(或者返回默認值):

public static void main(String[] args) { ImportTemplate importTemplate = getImportTemplateById(1); if (importTemplate == null) { return; } System.out.println(importTemplate.getUrl());}

比如,使用本文中的Optional。

使用哪種方式不重要,盡可能地避免NullPointerException異常才重要。

4. 參考

理解、學習與使用 Java 中的 Optional

總結

到此這篇關于Java中Optional使用的文章就介紹到這了,更多相關Java Optional使用內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
主站蜘蛛池模板: 鲁尔圆锥接头多功能测试仪-留置针测试仪-上海威夏环保科技有限公司 | 长沙广告公司|长沙广告制作设计|长沙led灯箱招牌制作找望城湖南锦蓝广告装饰工程有限公司 | 圆形振动筛_圆筛_旋振筛_三次元振动筛-河南新乡德诚生产厂家 | Eiafans.com_环评爱好者 环评网|环评论坛|环评报告公示网|竣工环保验收公示网|环保验收报告公示网|环保自主验收公示|环评公示网|环保公示网|注册环评工程师|环境影响评价|环评师|规划环评|环评报告|环评考试网|环评论坛 - Powered by Discuz! | 无锡市珂妮日用化妆品有限公司|珂妮日化官网|洗手液厂家 | 缝纫客| 德州万泰装饰 - 万泰装饰装修设计软装家居馆 | 宽带办理,电信宽带,移动宽带,联通宽带,电信宽带办理,移动宽带办理,联通宽带办理 | 南京种植牙医院【官方挂号】_南京治疗种植牙医院那个好_南京看种植牙哪里好_南京茀莱堡口腔医院 尼龙PA610树脂,尼龙PA612树脂,尼龙PA1010树脂,透明尼龙-谷骐科技【官网】 | 北京公积金代办/租房发票/租房备案-北京金鼎源公积金提取服务中心 | IWIS链条代理-ALPS耦合透镜-硅烷预处理剂-上海顶楚电子有限公司 lcd条形屏-液晶长条屏-户外广告屏-条形智能显示屏-深圳市条形智能电子有限公司 | COD分析仪|氨氮分析仪|总磷分析仪|总氮分析仪-圣湖Greatlake | 特材真空腔体_哈氏合金/镍基合金/纯镍腔体-无锡国德机械制造有限公司 | 福州时代广告制作装饰有限公司-福州广告公司广告牌制作,福州展厅文化墙广告设计, | jrs高清nba(无插件)直播-jrs直播低调看直播-jrs直播nba-jrs直播 上海地磅秤|电子地上衡|防爆地磅_上海地磅秤厂家–越衡称重 | 安全光栅|射频导纳物位开关|音叉料位计|雷达液位计|两级跑偏开关|双向拉绳开关-山东卓信机械有限公司 | 磁力反应釜,高压釜,实验室反应釜,高温高压反应釜-威海自控反应釜有限公司 | HDPE储罐_厂家-山东九州阿丽贝防腐设备 | 阴离子_阳离子聚丙烯酰胺厂家_聚合氯化铝价格_水处理絮凝剂_巩义市江源净水材料有限公司 | 商标转让-购买商标专业|放心的商标交易网-蜀易标商标网 | 耐酸碱胶管_耐腐蚀软管总成_化学品输送软管_漯河利通液压科技耐油耐磨喷砂软管|耐腐蚀化学软管 | 阿里巴巴诚信通温州、台州、宁波、嘉兴授权渠道商-浙江联欣科技提供阿里会员办理 | 电动球阀_不锈钢电动球阀_电动三通球阀_电动调节球阀_上海湖泉阀门有限公司 | 大型冰雕-景区冰雕展制作公司,3D创意设计源头厂家-[赛北冰雕] | 有声小说,听书,听小说资源库-听世界网 | 洗地机-全自动/手推式洗地机-扫地车厂家_扬子清洁设备 | 二氧化碳/活性炭投加系统,次氯酸钠发生器,紫外线消毒设备|广州新奥 | 存包柜厂家_电子存包柜_超市存包柜_超市电子存包柜_自动存包柜-洛阳中星 | 壹车网 | 第一时间提供新车_资讯_报价_图片_排行! | 东莞猎头公司_深圳猎头公司_广州猎头公司-广东万诚猎头提供企业中高端人才招聘服务 | 山东风淋室_201/304不锈钢风淋室净化设备厂家-盛之源风淋室厂家 翻斗式矿车|固定式矿车|曲轨侧卸式矿车|梭式矿车|矿车配件-山东卓力矿车生产厂家 | 光照全温振荡器(智能型)-恒隆仪器 | [官网]叛逆孩子管教_戒网瘾学校_全封闭问题青少年素质教育_新起点青少年特训学校 | 环比机械 | 奥运星-汽车性能网评-提供个性化汽车资讯| 烟雾净化器-滤筒除尘器-防爆除尘器-除尘器厂家-东莞执信环保科技有限公司 | 优考试_免费在线考试系统_培训考试系统_题库系统_组卷答题系统_匡优考试 | 重庆监控_电子围栏设备安装公司_门禁停车场管理系统-劲浪科技公司 | 恒温油槽-恒温水槽-低温恒温槽厂家-宁波科麦仪器有限公司 | 常州翔天实验仪器厂-恒温振荡器-台式恒温振荡器-微量血液离心机 恒温恒湿箱(药品/保健品/食品/半导体/细菌)-兰贝石(北京)科技有限公司 | 风信子发稿-专注为企业提供全球新闻稿发布服务 |