零合并运算符的替代方法



使用 Java,可以安全地访问深度嵌套引用,例如 a.b.c.d.e,我们通常必须在每个级别指定空检查或包装Optional s并使用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通常不受欢迎,但想知道这里的用法是否是一个合理的例外。

你可以写一个函数,它需要一个值和一个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);
}

对于两个深度,以及

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

三个深度,依此类推,对于更深的深度。

示例代码:

    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

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

不幸的是,我没有看到使代码更短的方法。

相关内容

  • 没有找到相关文章

最新更新