Java8以後的業務取值避免空指針的一種解法

寫業務代碼的時候,一般會遇到數據庫POJO對象轉換爲前端須要的VO對象,這時常常會遇到煩人的空指針問題,Java 8以前,咱們可能這麼寫:前端

  1. 對於對象field複製風格:
a.setCreateTime(b.getCreateTime().getTime());
a.setAmount(b.getPayed()+b.getVoucher());
  1. 對於裝飾器風格:
public Long getCreateTime() {
    return b.getCreateTime().getTime();
}
public Long getAmount() {
    return b.getPayed()+b.getVoucher()
}

很明顯,這些代碼會有空指針異常的風險.通常咱們會這麼修改:java

  1. 對於對象field複製風格:
if (b.getCreateTime()!= null) {
    a.setCreateTime(b.getCreateTime().getTime());
}
if (b.getPayed() != null) {
    a.setAmount(b.getPayed();     
} else {
    a.setAmount(0L);
}
if (b.getVoucher() != null) {
a.setAmount(a.getAmount()+b.getVoucher());
}
  1. 對於裝飾器風格:
public Long getCreateTime() {
    if (b.getCreateTime()!= null) {
        return b.getCreateTime().getTime();
    } else {
        return null;
    }
}
public Long getAmount() {
    Long result = 0L;
    if (b.getPayed() != null) {
        result += b.getPayed();
    }
    if (b.getVoucher() != null) {
        result += b.getVoucher();
    }
    return result;
}

Java8引入的Optional寫法:數據庫

  1. 對於對象field複製風格:
Optional.ofNullable(b.getCreateTime()).ifPresent(timestamp -> a.setCreateTime(timestamp.getTime()));
a.setAmount(Optional.ofNullable(b.getPayed()).orElse(0L) + Optional.ofNullable(b.getVoucher()).orElse(0L));
  1. 對於裝飾器風格:
public Long getCreateTime() {
    Optional<Timestamp> createTime = Optional.ofNullable(b.getCreateTime());
    if (createTime.isPresent()) {
        return createTime.get();
    } else {
        return null;
    }
}
public Long getAmount() {
    return Optional.ofNullable(b.getPayed()).orElse(0L) + Optional.ofNullable(b.getVoucher()).orElse(0L)
}

這樣依然很複雜,尤爲是嵌套多層以後。 更進一步,有沒有通用簡便的方法呢?聯想到Java8的Functional Interface以及咱們須要處理的異常只有空指針異常,能夠寫工具類:工具

import java.util.function.Supplier;

public class OptionalUtil {
    /**
     * 忽略NullPointerException的獲取
     * @param supplier
     * @param <T>
     * @return 若是有空指針,返回null
     */
    public static <T> T orNull(Supplier<T> supplier) {
        try {
            return supplier.get();
        } catch (NullPointerException e) {
            return null;
        }
    }

    /**
     * 忽略NullPointerException的獲取
     *
     * @param supplier
     * @param or
     * @param <T>
     * @return 若是有空指針,返回or
     */
    public static <T> T or(Supplier<T> supplier, T or) {
        try {
            T t = supplier.get();
            if (t != null) {
                return t;
            }
            return or;
        } catch (NullPointerException e) {
            return or;
        }
    }
}

這樣,咱們的代碼就變得簡潔多了:指針

  1. 對於對象field複製風格:
a.setCreateTime(OptionalUtil.orNull(() -> b.getCreateTime().getTime()));
a.setAmount(OptionalUtil.or(() -> b.getPayed(), 0L) + OptionalUtil.or(() -> b.getAmount(), 0L));
  1. 對於裝飾器風格:
public Long getCreateTime() {
    return OptionalUtil.orNull(() -> b.getCreateTime().getTime());
}
public Long getAmount() {
    return OptionalUtil.or(() -> b.getPayed(), 0L) + OptionalUtil.or(() -> b.getAmount(), 0L);
}
相關文章
相關標籤/搜索