作者:京東物流 王亞寧
1、NPE是什么?
NPE:NullPointerException(空指針異常)。可以說(shuō)自Null的誕生以來(lái)它就讓無(wú)數(shù)的程序員為之哀嚎,也是無(wú)數(shù)系統(tǒng)Bug的來(lái)源。托尼·霍爾(Tony Hoare),Null的發(fā)明者也表示過(guò)這是他十億美元的錯(cuò)誤。當(dāng)程序試圖在空引用(null)上調(diào)用方法或訪(fǎng)問(wèn)屬性時(shí),JVM會(huì)拋出NPE。例如:
String str = null; int length = str.length(); // 這里會(huì)拋出NPE
1.1、NPE的常見(jiàn)原因
未初始化的對(duì)象:變量聲明后未賦值,即默認(rèn)為null。
方法返回null:方法可能返回一個(gè)對(duì)象或null,但調(diào)用者未進(jìn)行null檢查。
集合中的null元素:集合操作中插入了null,后續(xù)操作未處理。
多線(xiàn)程環(huán)境中的競(jìng)態(tài)條件:一個(gè)線(xiàn)程修改對(duì)象狀態(tài)為null,另一個(gè)線(xiàn)程未及時(shí)檢查。
1.2、NPE的影響
程序崩潰:未處理的NPE會(huì)導(dǎo)致程序終止,影響用戶(hù)體驗(yàn)。
調(diào)試?yán)щy:NPE的堆棧信息可能不直觀(guān),定位問(wèn)題源頭耗時(shí)。
代碼質(zhì)量下降:頻繁的NPE表明代碼缺乏健壯的null處理機(jī)制。
2、Optional庫(kù)介紹
為了應(yīng)對(duì)NPE問(wèn)題,Java 8引入了Optional類(lèi),它是一個(gè)容器對(duì)象,可以包含或不包含非null的值。通過(guò)Optional,開(kāi)發(fā)者可以顯式地表示一個(gè)值是可選的,從而強(qiáng)制進(jìn)行null檢查,減少NPE的發(fā)生。
2.1、Optional的基本用法
創(chuàng)建Optional對(duì)象 Optional optional = Optional.of("Hello"); // 創(chuàng)建包含值的Optional Optional emptyOptional = Optional.empty(); // 創(chuàng)建空的Optional Optional nullableOptional = Optional.ofNullable(null); // 可以接受null
獲取值 // 使用get()獲取值,如果為空則拋出NoSuchElementException optional.get(); // 使用orElse()提供默認(rèn)值 String value = optional.orElse("Default"); // 使用orElseGet()提供默認(rèn)值的Supplier String value = optional.orElseGet(() -> "Default"); // 使用orElseThrow()在值為空時(shí)拋出異常 String value = optional.orElseThrow(() -> new IllegalArgumentException("Value is null"));
處理值 // 使用ifPresent()在值存在時(shí)執(zhí)行操作 optional.ifPresent(val -> System.out.println(val)); // 使用map()轉(zhuǎn)換值 Optional lengthOptional = optional.map(String::length); // 使用flatMap()處理嵌套的Optional Optional> nestedOptional = Optional.of(Optional.of("Nested")); Optional flatOptional = nestedOptional.flatMap(opt -> opt);
2.2、Optional的優(yōu)勢(shì)
明確的意圖:方法返回Optional表明返回值可能為空,增強(qiáng)代碼的可讀性。
強(qiáng)制null檢查:通過(guò)Optional的方法鏈,開(kāi)發(fā)者必須處理可能的空值,減少遺漏。
函數(shù)式編程支持:與Lambda表達(dá)式和Stream API無(wú)縫結(jié)合,簡(jiǎn)化代碼邏輯。
3、最佳實(shí)例示例
示例背景
假設(shè)有一個(gè)用戶(hù)類(lèi)User,包含一個(gè)地址類(lèi)Address,而地址類(lèi)中又包含城市信息City。在獲取用戶(hù)的城市名稱(chēng)時(shí),存在多級(jí)空指針的風(fēng)險(xiǎn)。
public class User { private Address address; public Address getAddress() { return address; } } public class Address { private City city; public City getCity() { return city; } } public class City { private String name; public String getName() { return name; } }
使用傳統(tǒng)方式處理NPE
在沒(méi)有使用Optional的情況下,獲取城市名稱(chēng)可能需要多級(jí)null檢查:
public String getUserCityName(User user) { if (user != null) { Address address = user.getAddress(); if (address != null) { City city = address.getCity(); if (city != null) { return city.getName(); } } } return "Unknown"; }
上述代碼層層嵌套,邏輯復(fù)雜,且易于遺漏某一級(jí)的null檢查。并且代碼也不容易閱讀
使用Optional簡(jiǎn)化代碼
利用Optional,可以將多級(jí)null檢查轉(zhuǎn)化為鏈?zhǔn)秸{(diào)用,代碼更加簡(jiǎn)潔明了:
public String getUserCityName(Optional userOptional) { return userOptional .map(User::getAddress) .map(Address::getCity) .map(City::getName) .orElse("Unknown"); }
另一個(gè)實(shí)例:處理方法返回值
假設(shè)有一個(gè)方法findUserById,可能返回一個(gè)User對(duì)象或null。使用Optional可以?xún)?yōu)雅地處理返回值。
public Optional findUserById(String userId) { User user = userRepository.findById(userId); // 可能返回null return Optional.ofNullable(user); }
調(diào)用方可以這樣使用:
findUserById("12345") .map(User::getAddress) .map(Address::getCity) .map(City::getName) .ifPresent(cityName -> System.out.println("User city: " + cityName));
如果User不存在或其地址、城市信息為null,上述代碼不會(huì)執(zhí)行ifPresent中的打印操作,避免了NPE的風(fēng)險(xiǎn)。
總結(jié)
通過(guò)合理使用Java 8的Optional類(lèi),我們開(kāi)發(fā)者可以有效減少NullPointerException的發(fā)生,提高代碼的健壯性和可維護(hù)性。然而,Optional并非萬(wàn)能,需結(jié)合具體場(chǎng)景合理使用。掌握Optional的使用技巧和最佳實(shí)踐,將有助于編寫(xiě)更安全、優(yōu)雅的Java代碼,真正做到“善用Optional,告別NPE”。
審核編輯 黃宇
-
JAVA
+關(guān)注
關(guān)注
20文章
2983瀏覽量
106496 -
null
+關(guān)注
關(guān)注
0文章
19瀏覽量
4068
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
JDK8新增的Optional類(lèi)的常用方法
完善用戶(hù)資料任務(wù)是不是有BUG?
安裝使用Qualcomm Snapdragon神經(jīng)處理引擎(NPE) SDK
Snapdragon NPE SDK的環(huán)境配置
Snapdragon NPE SDK配置模型文件的轉(zhuǎn)換和apk用例
【看動(dòng)畫(huà),學(xué)知識(shí)】告別山寨機(jī)!手機(jī)音質(zhì)測(cè)定,快,穩(wěn),準(zhǔn)!
2009美國(guó)國(guó)際塑料展/美國(guó)塑料展/NPE-----金彼岸
利用Ajax與ExtJS 改善用戶(hù)體驗(yàn)

JDK8 Optional類(lèi)新特性
Facebook和Qualcomm合作優(yōu)化Caffe2和Snapdragon NPE
高通推出神經(jīng)處理引擎(NPE)SDK,打造AI應(yīng)用新優(yōu)勢(shì)
JAVA8提供了Optional類(lèi)來(lái)優(yōu)化這種寫(xiě)法
認(rèn)識(shí)Optional并使用
E10A-USB Optional 38-Pin User System Interface Cable HS0005ECK01H 用戶(hù)手冊(cè)

善用可靠且性?xún)r(jià)比高的隔離技術(shù)來(lái)應(yīng)對(duì)高電壓設(shè)計(jì)挑戰(zhàn)

評(píng)論