自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

瞧瞧別人家的判空,那叫一個優(yōu)雅!

開發(fā) 前端
我們在日常開發(fā)中的entity對象,一般會使用Lombok框架中的注解,來實現(xiàn)getter/setter方法。

一、傳統(tǒng)判空的血淚史

某互聯(lián)網(wǎng)金融平臺因費用計算層級的空指針異常,導(dǎo)致凌晨產(chǎn)生9800筆錯誤交易。

DEBUG日志顯示問題出現(xiàn)在如下代碼段:

// 錯誤示例
BigDecimal amount = user.getWallet().getBalance().add(new BigDecimal("100"));

此類鏈?zhǔn)秸{(diào)用若中間環(huán)節(jié)出現(xiàn)null值,必定導(dǎo)致NPE。

初級階段開發(fā)者通常寫出多層嵌套式判斷:

if(user != null){
    Wallet wallet = user.getWallet();
    if(wallet != null){
        BigDecimal balance = wallet.getBalance();
        if(balance != null){
            // 實際業(yè)務(wù)邏輯
        }
    }
}

這種寫法既不優(yōu)雅又影響代碼可讀性。

那么,我們該如何優(yōu)化呢?

二、Java 8+時代的判空革命

Java8之后,新增了Optional類,它是用來專門判空的。

能夠幫你寫出更加優(yōu)雅的代碼。

1. Optional黃金三板斧

// 重構(gòu)后的鏈?zhǔn)秸{(diào)用
BigDecimal result = Optional.ofNullable(user)
    .map(User::getWallet)
    .map(Wallet::getBalance)
    .map(balance -> balance.add(new BigDecimal("100")))
    .orElse(BigDecimal.ZERO);

高級用法:條件過濾

Optional.ofNullable(user)
    .filter(u -> u.getVipLevel() > 3)
    .ifPresent(u -> sendCoupon(u)); // VIP用戶發(fā)券

2. Optional拋出業(yè)務(wù)異常

BigDecimal balance = Optional.ofNullable(user)
    .map(User::getWallet)
    .map(Wallet::getBalance)
    .orElseThrow(() -> new BusinessException("用戶錢包數(shù)據(jù)異常"));

3. 封裝通用工具類

public class NullSafe {
    
    // 安全獲取對象屬性
    public static <T, R> R get(T target, Function<T, R> mapper, R defaultValue) {
        return target != null ? mapper.apply(target) : defaultValue;
    }
    
    // 鏈?zhǔn)桨踩僮?    public static <T> T execute(T root, Consumer<T> consumer) {
        if (root != null) {
            consumer.accept(root);
        }
        return root;
    }
}

// 使用示例
NullSafe.execute(user, u -> {
    u.getWallet().charge(new BigDecimal("50"));
    logger.info("用戶{}已充值", u.getId());
});

三、現(xiàn)代化框架的判空銀彈

4. Spring實戰(zhàn)技巧

Spring中自帶了一些好用的工具類,比如:CollectionUtils、StringUtils等,可以非常有效的進(jìn)行判空。

具體代碼如下:

// 集合判空工具
List<Order> orders = getPendingOrders();
if (CollectionUtils.isEmpty(orders)) {
    return Result.error("無待處理訂單");
}

// 字符串檢查
String input = request.getParam("token");
if (StringUtils.hasText(input)) {
    validateToken(input); 
}

5. Lombok保駕護(hù)航

我們在日常開發(fā)中的entity對象,一般會使用Lombok框架中的注解,來實現(xiàn)getter/setter方法。

其實,這個框架中也提供了@NonNull等判空的注解。

比如:

@Getter
@Setter
public class User {
    @NonNull // 編譯時生成null檢查代碼
    private String name;
    
    private Wallet wallet;
}

// 使用構(gòu)造時自動判空
User user = new User(@NonNull "張三", wallet);

四、工程級解決方案

6. 空對象模式

public interface Notification {
    void send(String message);
}

// 真實實現(xiàn)
public class EmailNotification implements Notification {
    @Override
    public void send(String message) {
        // 發(fā)送郵件邏輯
    }
}

// 空對象實現(xiàn)
public class NullNotification implements Notification {
    @Override
    public void send(String message) {
        // 默認(rèn)處理
    }
}

// 使用示例
Notification notifier = getNotifier();
notifier.send("系統(tǒng)提醒"); // 無需判空

7. Guava的Optional增強

其實Guava工具包中,給我們提供了Optional增強的功能。

比如:

import com.google.common.base.Optional;

// 創(chuàng)建攜帶缺省值的Optional
Optional<User> userOpt = Optional.fromNullable(user).or(defaultUser);

// 鏈?zhǔn)讲僮髋浜螰unction
Optional<BigDecimal> amount = userOpt.transform(u -> u.getWallet())
                                    .transform(w -> w.getBalance());

Guava工具包中的Optional類已經(jīng)封裝好了,我們可以直接使用。

五、防御式編程進(jìn)階

8. Assert斷言式攔截

其實有些Assert斷言類中,已經(jīng)做好了判空的工作,參數(shù)為空則會拋出異常。

這樣我們就可以直接調(diào)用這個斷言類。

例如下面的ValidateUtils類中的requireNonNull方法,由于它內(nèi)容已經(jīng)判空了,因此,在其他地方調(diào)用requireNonNull方法時,如果為空,則會直接拋異常。

我們在業(yè)務(wù)代碼中,直接調(diào)用requireNonNull即可,不用寫額外的判空邏輯。

例如:

public class ValidateUtils {
    public static <T> T requireNonNull(T obj, String message) {
        if (obj == null) {
            throw new ServiceException(message);
        }
        return obj;
    }
}

// 使用姿勢
User currentUser = ValidateUtils.requireNonNull(
    userDao.findById(userId), 
    "用戶不存在-ID:" + userId
);

9. 全局AOP攔截

我們在一些特殊的業(yè)務(wù)場景種,可以通過自定義注解 + 全局AOP攔截器的方式,來實現(xiàn)實體或者字段的判空。

例如:

@Aspect
@Component
public class NullCheckAspect {
    
    @Around("@annotation(com.xxx.NullCheck)")
    public Object checkNull(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (arg == null) {
                throw new IllegalArgumentException("參數(shù)不可為空");
            }
        }
        return joinPoint.proceed();
    }
}

// 注解使用
public void updateUser(@NullCheck User user) {
    // 方法實現(xiàn)
}

六、實戰(zhàn)場景對比分析

場景1:深層次對象取值

// 舊代碼(4層嵌套判斷)
if (order != null) {
    User user = order.getUser();
    if (user != null) {
        Address address = user.getAddress();
        if (address != null) {
            String city = address.getCity();
            // 使用city
        }
    }
}

// 重構(gòu)后(流暢鏈?zhǔn)剑?String city = Optional.ofNullable(order)
    .map(Order::getUser)
    .map(User::getAddress)
    .map(Address::getCity)
    .orElse("未知城市");

場景2:批量數(shù)據(jù)處理

List<User> users = userService.listUsers();

// 傳統(tǒng)寫法(顯式迭代判斷)
List<String> names = new ArrayList<>();
for (User user : users) {
    if (user != null && user.getName() != null) {
        names.add(user.getName());
    }
}

// Stream優(yōu)化版
List<String> nameList = users.stream()
    .filter(Objects::nonNull)
    .map(User::getName)
    .filter(Objects::nonNull)
    .collect(Collectors.toList());

七、性能與安全的平衡藝術(shù)

上面介紹的這些方案都可以使用,但除了代碼的可讀性之外,我們還需要考慮一下性能因素。

下面列出了上面的幾種在CPU消耗、內(nèi)存只用和代碼可讀性的對比:

方案

CPU消耗

內(nèi)存占用

代碼可讀性

適用場景

多層if嵌套



★☆☆☆☆

簡單層級調(diào)用

Java Optional



★★★★☆

中等復(fù)雜度業(yè)務(wù)流

空對象模式



★★★★★

高頻調(diào)用的基礎(chǔ)服務(wù)

AOP全局?jǐn)r截



★★★☆☆

接口參數(shù)非空驗證

黃金法則

  • Web層入口強制參數(shù)校驗
  • Service層使用Optional鏈?zhǔn)教幚?/li>
  • 核心領(lǐng)域模型采用空對象模式

八、擴(kuò)展技術(shù)

除了,上面介紹的常規(guī)判空之外,下面再給大家介紹兩種擴(kuò)展的技術(shù)。

Kotlin的空安全設(shè)計

雖然Java開發(fā)者無法直接使用,但可借鑒其設(shè)計哲學(xué):

val city = order?.user?.address?.city ?: "default"

JDK 14新特性預(yù)覽

// 模式匹配語法嘗鮮
if (user instanceof User u && u.getName() != null) {
    System.out.println(u.getName().toUpperCase());
}

總之,優(yōu)雅判空不僅是代碼之美,更是生產(chǎn)安全底線。

本文分享了代碼判空的10種方案,希望能夠幫助你編寫出既優(yōu)雅又健壯的Java代碼。

責(zé)任編輯:武曉燕 來源: 蘇三說技術(shù)
相關(guān)推薦

2024-11-12 08:20:31

2024-10-24 08:21:33

2025-04-08 08:20:33

2022-12-12 08:14:47

2024-12-02 00:59:30

Spring

2025-04-22 08:20:51

2025-03-11 08:20:58

2025-02-28 08:21:00

2015-09-24 09:22:16

nodejs頁面始末

2020-11-03 16:00:33

API接口微服務(wù)框架編程語言

2020-11-17 09:34:31

API接口后端

2017-11-12 21:32:52

戴爾

2017-09-22 13:22:59

大數(shù)據(jù)南京大學(xué)宿舍

2016-01-08 09:49:19

DockerDocker案例云應(yīng)用開發(fā)

2023-12-30 20:04:51

MyBatis框架數(shù)據(jù)

2021-07-14 06:31:08

京東互聯(lián)網(wǎng)加薪

2019-06-11 09:35:50

戴爾

2021-01-20 05:42:27

RabbitMQMQ vhost

2017-06-13 14:15:51

戴爾協(xié)同計算汽車神話

2025-04-02 12:20:00

開發(fā)代碼函數(shù)
點贊
收藏

51CTO技術(shù)棧公眾號