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); }