如果object(或任何函数结果)为null,则调用函数应返回默认值

时间:2013-07-25 12:18:21

标签: java null null-check

是否可以将以下代码包装在可重用的函数中?

编辑: 这只是一个例子,我想要一个适用于所有递归深度的工作解决方案

我想要的是生成以下代码:

if (MyObject o == null || 
    o.getSubObject() == null ||
    o..getSubObject().getSubSubObject() == null /*|| 
    ... */)
    return defaultValue;
return o.getSubObject().getSubObject()/*...*/.getDesiredValue();

通过调用

之类的东西
Object defaultValue = null;
Object result = NullSafeCall(o.getSubObject().getSubObject()/*...*/.getDesiredValue(), defaultValue);

seond代码块只是一个想法,我不在乎它的样子,我想要的是,如果需要,我可以在调用更深层函数之前避免所有null检查...

注射可以做到这一点,但没有其他/更容易的解决方案吗?从来没有看过注射......

EDIT2: 另一种语言示例:http://groovy.codehaus.org/Operators#Operators-SafeNavigationOperator

5 个答案:

答案 0 :(得分:1)

不是真的,你用这种方式编写的任何代码看起来都很糟糕和/或使用非常慢的反射。除非您使用可以理解和更改您已编写的代码的实际Java预处理器。

更好(但与相当多的重构相关联)方法是确保所讨论的值不可能为空。例如,您可以修改各个访问器(getSubObject()getDesiredValue()),使其永远不会返回null:使它们返回默认值。默认值上的访问器依次返回默认值。

答案 1 :(得分:1)

Java8有助于获得最接近您的语法,我怀疑它具有良好的性能;

// Evaluate with default 5 if anything returns null.
int result = Optional.eval(5, o, x->x.getSubObject(), x->x.getDesiredValue());

这可以使用此实用程序类完成;

class Optional {
    public static <T, Tdef, T1> Tdef eval(Tdef def, T input, Function<T,T1> fn1,
                                          Function<T1, Tdef> fn2)
    {
        if(input == null) return def;
        T1 res1 = fn1.apply(input);
        if(res1 == null) return def;
        return fn2.apply(res1);
    }
}

遗憾的是,你需要为链中的每个方法调用定义一个单独的eval(),所以你可能想要定义一些,但编译时类型安全且可重用几乎任何调用/类型。

答案 2 :(得分:0)

你可以做这样的事情

public static Object  NullSafeCall(MyObject o,Object defaultValue){
    if ( o == null || o.getSubObject() == null)
    {
        return defaultValue;
    }
    else 
    {
        return o.getSubObject().getDesiredValue();
    }
}

现在您可以按如下方式调用此方法

 Object result = NullSafeCall(o, defaultValue);

答案 3 :(得分:0)

我建议只更换

Object result = NullSafeCall(o.getSubObject().getDesiredValue(), defaultValue);

Object result = (o == null || o.subObject == null) ? defaultVlue : o.getSubObject().getDesiredValue();

只有在可以重复使用时才创建方法......

答案 4 :(得分:0)

你想要的是不可能的。必须了解使用以下语法:Object result = NullSafeCall(o.getSubObject().getSubObject() ...); {<1}}的部分将在之前评估任何控件传递给函数/方法,从而抛出异常。

在执行此类代码之前,需要具有某种类型的上下文。我能想到的最接近这个,可以使用匿名内部类来完成,如下例所示:

o.getSubObject().getSubObject()