搜尋
首頁Javajava教程Java中如何處理空指標異常

NullPointerException 是Java 程式碼中最常見的例外,我將其最可能出現的場景歸為以下5 種:

  • 參數值是Integer 等包裝類型,使用時因為自動拆箱出現了空白指標例外;

  • 字串比較出現空指標例外;

  • ##諸如ConcurrentHashMap 這樣的容器不支援Key 和Value 為null,強行put null 的Key 或Value 會出現空指標異常;

  • A 物件包含了B,在透過A 物件的欄位取得B 之後,沒有對欄位判空就級聯呼叫B 的方法出現空指標異常;方法或遠端服務回傳的List 不是空而是null,沒有進行判空就直接呼叫List 的方法出現空指標異常。

  • private List<String> wrongMethod(FooService fooService, Integer i, String s, String t) {
        log.info("result {} {} {} {}", i + 1, s.equals("OK"), s.equals(t),
                new ConcurrentHashMap<String, String>().put(null, null));
        if (fooService.getBarService().bar().equals("OK"))
            log.info("OK");
        return null;
    }
    
    @GetMapping("wrong")
    public int wrong(@RequestParam(value = "test", defaultValue = "1111") String test) {
        return wrongMethod(test.charAt(0) == &#39;1&#39; ? null : new FooService(),
                test.charAt(1) == &#39;1&#39; ? null : 1,
                test.charAt(2) == &#39;1&#39; ? null : "OK",
                test.charAt(3) == &#39;1&#39; ? null : "OK").size();
    }
    
    class FooService {
        @Getter
        private BarService barService;
    
    }
    
    class BarService {
        String bar() {
            return "OK";
        }
    }
修正想法如下:

  • #對於Integer 的判空,可以使用Optional.ofNullable 來建構一個Optional,然後使用orElse(0 ) 把null 替換為預設值再進行1 操作。對於String 和字面量的比較,可以把字面量放在前面,例如"OK".equals(s),這樣即使s 是null 也不會出現空指標異常;而對於兩個可能為null 的字串變數的equals 比較,可以使用Objects.equals,它會做判空處理。

  • 對於 ConcurrentHashMap,既然其 Key 和 Value 不支援 null,修復方式就是不要把 null 存進去。 HashMap 的 Key 和 Value 可以存入 null,而 ConcurrentHashMap 看似是 HashMap 的線程安全版本,卻不支援 null 值的 Key 和 Value,這是容易產生誤解的地方。

  • 對於類似fooService.getBarService().bar().equals(“OK”) 的級聯調用,需要判空的地方有很多,包括fooService、getBarService() 方法的回傳值,以及bar 方法傳回的字串。如果使用 if-else 來判空的話可能需要好幾行程式碼,但使用 Optional 的話一行程式碼就夠了。

  • 對於rightMethod 傳回的List,由於無法確認其是否為null,所以在呼叫size 方法獲得清單大小之前,同樣可以使用Optional.ofNullable 包裝一下傳回值,然後透過. orElse(Collections.emptyList()) 實作在List 為null 的時候得到一個空的List,最後再呼叫size 方法。

  • private List<String> rightMethod(FooService fooService, Integer i, String s, String t) {
        log.info("result {} {} {} {}", Optional.ofNullable(i).orElse(0) + 1, "OK".equals(s), Objects.equals(s, t), new HashMap<String, String>().put(null, null));
        Optional.ofNullable(fooService)
                .map(FooService::getBarService)
                .filter(barService -> "OK".equals(barService.bar()))
                .ifPresent(result -> log.info("OK"));
        return new ArrayList<>();
    }
    
    @GetMapping("right")
    public int right(@RequestParam(value = "test", defaultValue = "1111") String test) {
        return Optional.ofNullable(rightMethod(test.charAt(0) == &#39;1&#39; ? null : new FooService(),
                test.charAt(1) == &#39;1&#39; ? null : 1,
                test.charAt(2) == &#39;1&#39; ? null : "OK",
                test.charAt(3) == &#39;1&#39; ? null : "OK"))
                .orElse(Collections.emptyList()).size();
    }
  • 我們根據業務需求分別對姓名、年齡和暱稱進行更新:對於姓名,我們認為客戶端傳null 是希望把姓名重設為空,允許這樣的操作,使用Optional 的orElse 方法一鍵把空轉換為空字串即可。

  • 對於年齡,我們認為如果客戶端希望更新年齡就必須傳一個有效的年齡,年齡不存在重置操作,可以使用Optional 的orElseThrow 方法在值為空的時候拋出IllegalArgumentException。

  • 對於暱稱,因為資料庫中姓名不可能為 null,所以可以放心地把暱稱設為 guest 加上資料庫取出的姓名。

  • @PostMapping("right")
    public UserEntity right(@RequestBody UserDto user) {
        if (user == null || user.getId() == null)
            throw new IllegalArgumentException("用户Id不能为空");
    
        UserEntity userEntity = userEntityRepository.findById(user.getId())
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
    
        if (user.getName() != null) {
            userEntity.setName(user.getName().orElse(""));
        }
        userEntity.setNickname("guest" + userEntity.getName());
        if (user.getAge() != null) {
            userEntity.setAge(user.getAge().orElseThrow(() -> new IllegalArgumentException("年龄不能为空")));
        }
        return userEntityRepository.save(userEntity);
    }

以上是Java中如何處理空指標異常的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:亿速云。如有侵權,請聯絡admin@php.cn刪除
IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的?IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的?Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本啟動Spring...

如何優雅地獲取實體類變量名構建數據庫查詢條件?如何優雅地獲取實體類變量名構建數據庫查詢條件?Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

如何利用Redis緩存方案高效實現產品排行榜列表的需求?如何利用Redis緩存方案高效實現產品排行榜列表的需求?Apr 19, 2025 pm 11:36 PM

Redis緩存方案如何實現產品排行榜列表的需求?在開發過程中,我們常常需要處理排行榜的需求,例如展示一個�...

Java對像如何安全地轉換為數組?Java對像如何安全地轉換為數組?Apr 19, 2025 pm 11:33 PM

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

如何將姓名轉換為數字以實現排序並保持群組中的一致性?如何將姓名轉換為數字以實現排序並保持群組中的一致性?Apr 19, 2025 pm 11:30 PM

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品?電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品?Apr 19, 2025 pm 11:27 PM

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

在Idea中如何設置SpringBoot項目默認運行配置列表以便團隊成員共享?在Idea中如何設置SpringBoot項目默認運行配置列表以便團隊成員共享?Apr 19, 2025 pm 11:24 PM

在Idea中如何設置SpringBoot項目默認運行配置列表在使用IntelliJ...

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。