首頁 > Java > java教程 > 主體

Java中如何處理空指標異常

WBOY
發布: 2023-05-10 17:43:06
轉載
1751 人瀏覽過

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中文網其他相關文章!

相關標籤:
來源:yisu.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板