用于避免bean对象连点方法调用报空指针异常,排查困难。

import java.util.List;
import java.util.Objects;
import java.util.function.Function;

public class ObjectUtil {

    private ObjectUtil() {}

    /**
     * 解决bean连点导致空指针异常错误难排查问题。具体使用方法看测试用例
     * @param <R>
     */
    public static class NoNullObject<R> {

        private StringBuilder sb;

        private R r;

        public static <R> NoNullObject<R> build(R r) {
            return new NoNullObject(r);
        }

        private NoNullObject(R r) {
            Objects.requireNonNull(r);
            this.r = r;
            sb = new StringBuilder();
            sb.append(r.getClass());
        }

        private NoNullObject(R r, StringBuilder sb) {
            this.sb = sb;
            this.r = r;
            if(r == null) {
                throw new NullPointerException(sb.toString());
            }
        }

        public <V> NoNullObject<V> then(Function<? super R, ? extends V> after, String functionName) {
            Objects.requireNonNull(after);
            sb.append('.');
            sb.append(functionName);
            return new NoNullObject<>(after.apply(r), sb);
        }

        public <V> NoNullObject<V> listThen(Function<? super R, ? extends V> after, int index) {
            Objects.requireNonNull(after);
            List l = (List) r;
            if(index < 0) {
                throw new RuntimeException("index must not < 0");
            }
            if(l.size() <= index) {
                throw new RuntimeException(sb.toString() + " List size(" + l.size() + ") not <= index(" + index + ")");
            }
            sb.append('.');
            sb.append("get("+ index +")");
            return new NoNullObject<>(after.apply(r), sb);
        }

        public R getResult() {
            return r;
        }

    }


    /**
     * 解决bean连点导致空指针异常错误难排查问题。具体使用方法看测试用例
     * @param <T>
     * @param <R>
     */
    public interface NoNullFunction<T, R> {

        R apply(T t);

        static <T> NoNullFunction<T, T> identity(StringBuilder sb) {
            return t -> {
                sb.append(t.getClass().getName());
                return t;
            };
        }

        default <V> NoNullFunction<T, V> then(Function<? super R, ? extends V> after, StringBuilder sb, String functionName) {
            Objects.requireNonNull(after);
            return (T t) -> {
                R r = apply(t);
                if(r == null) {
                    throw new NullPointerException(sb.toString());
                }
                sb.append('.');
                sb.append(functionName);
                return after.apply(r);
            };
        }

        default <V> NoNullFunction<T, V> listThen(Function<? super R, ? extends V> after, int index, StringBuilder sb) {
            Objects.requireNonNull(after);
            return (T t) -> {
                R r = apply(t);
                //使用不规范这里很可能转换失败。
                List l = (List) r;
                if(r == null) {
                    throw new NullPointerException(sb.toString());
                }
                if(index < 0) {
                    throw new RuntimeException("index must not < 0");
                }
                if(l.size() <= index) {
                    throw new RuntimeException(sb.toString() + " List size(" + l.size() + ") not <= index(" + index + ")");
                }
                sb.append('.');
                sb.append("get("+ index +")");
                return after.apply(r);
            };
        }
    }

    /**
     * @param o
     * @param f
     * @param <T>
     * @return
     */
    public static <T, R> R noNullFunctionGet(T o, NoNullFunction<T,R> f, StringBuilder sb) {
        if(f == null || o == null) {
            throw new NullPointerException("f and o must not null!");
        }
        R r = f.apply(o);
        if(r == null) {
            throw new NullPointerException(sb.toString());
        }
        return r;
    }

} 

下面是使用方式

对于数组的下标取值可能报的异常,需要个人在Function里进行处理

    @Test
    public void test1() {
        Order o = new Order();
        OrderPackage p = new OrderPackage();
        o.setPackages(new ArrayList<>());
        o.setPackages(Collections.singletonList(p));
        p.setLogisticsNumber("123456");

        ObjectUtil.NoNullObject<String> nno = ((ObjectUtil.NoNullObject<Order>) new ObjectUtil.NoNullObject(o))
                .then(a -> a.getPackages(), "getPackages()")
                .listThen(a -> a.get(0), 0)
                .then(a -> a.getLogisticsNumber(), "getLogisticsNumber()");

        System.out.println(nno.getResult());
    }

    @Test
    public void test() {
        Order o = new Order();
        OrderPackage p = new OrderPackage();
//        o.setPackages(new ArrayList<>());
//        o.setPackages(Collections.singletonList(p));
//        p.setLogisticsNumber("123456");

        //后面可以写一个生成代码程序,将o.getPackages().get(O).getLogisticsNumber() 转换为下面代码
        StringBuilder sb = new StringBuilder();
        ObjectUtil.NoNullFunction<Order, Order> f = ObjectUtil.NoNullFunction.identity(sb);
        ObjectUtil.NoNullFunction<Order, String> r =
                f.then(a -> a.getPackages(), sb,"getPackages()")
                    .listThen(a -> a.get(0), 0,  sb)
                    .then(a -> a.getLogisticsNumber(),  sb,"getLogisticsNumber()");

        String result = ObjectUtil.noNullFunctionGet(o, r, sb);
        System.out.println(result);
    }
原文地址:https://www.cnblogs.com/math-and-it/p/14912923.html