Null Coalescing Operator的替代方案

时间:2017-05-17 08:19:47

标签: java nullpointerexception null null-coalescing-operator

使用Java,可以安全地访问深层嵌套引用 a.b.c.d.e,我们通常必须在每个级别指定空检查或包装Optional并使用orElse()。 (与Kotlin / C#等语言不同,其中a?.b?.c?.d?.e或类似作品。

我想知道以下帮助方法是否是一个合理的选择:

public <T> T valueOrNull(Supplier<T> expression) {
    try {
        return expression.get();
    } catch (NullPointerException e) {
        return null;
    }
}

然后可以安全地使用value = valueOrNull(() -> a.b.c.d.e)

注意:我理解,由于性能原因等原因,捕捉NullPointerException通常不赞成,但是想知道这里的用法是否是一个合理的例外。

1 个答案:

答案 0 :(得分:1)

你可以写一个带值的函数和一个getter来转换它,就像这样

public static <T1, T2> T1 coalesce(T2 value, Function<T2,T1> f1){
    return f1.apply(value);
}

然后你会像coalesce(value, Clazz::getA)那样打电话。

对于链中的每一步,您需要在合并函数中使用附加函数,如此

public static <T1, T2, T3> T1 coalesce(T3 value, Function<T3,T2> f1, Function<T2,T1> f2){
    T2 t2 = f1.apply(value);
    if(t2 == null)
        return null;    
    return f2.apply(t2);
}

深度为2,

public static <T1, T2, T3, T4> T1 coalesce(T4 value, Function<T4,T3> f1, Function<T3,T2> f2, Function<T2,T1> f3){
    T3 t3 = f1.apply(value);
    if(t3 == null)
        return null;
    T2 t2 = f2.apply(t3);
    if(t2 == null)
        return null;
    return f3.apply(t2);
}

深度为3,等等进一步深度。

示例代码:

    A test1 = new A(null);
    A test2 = new A(new B(null));
    A test3 = new A(new B(new C(null)));
    A test4 = new A(new B(new C("1234")));

    System.out.println(coalesce(test1, A::getB, B::getC, C::getS));
    System.out.println(coalesce(test2, A::getB, B::getC, C::getS));
    System.out.println(coalesce(test3, A::getB, B::getC, C::getS));
    System.out.println(coalesce(test4, A::getB, B::getC, C::getS));

    System.out.println(coalesce(test2, A::getB));
    System.out.println(coalesce(test3, A::getB, B::getC));

A是具有类B成员的类,B是具有类C成员的类,C是具有类String成员的类,具有适当的getter。输出符合预期:

null
null
null
1234    
B@776ec8df
C@41629346

前三种情况为空,其中C中的字符串为null,第四种具有字符串的值,第五种和第六种返回的对象分别为B和C类型。

遗憾的是,我没有办法让代码更短。