检查“get”调用链是否为空

新手上路,请多包涵

假设我想执行以下命令:

 house.getFloor(0).getWall(WEST).getDoor().getDoorknob();

为了避免 NullPointerException,我必须在以下情况下执行以下操作:

 if (house != null && house.getFloor(0) && house.getFloor(0).getWall(WEST) != null
  && house.getFloor(0).getWall(WEST).getDoor() != null) ...

有没有一种方法或已经存在的 Utils 类可以更优雅地执行此操作,让我们说类似下面的内容?

 checkForNull(house.getFloor(0).getWall(WEST).getDoor().getDoorknob());

原文由 user321068 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 526
2 个回答

最好的方法是 避免 链条。如果您不熟悉 Demeter 法则 (LoD),我认为您应该熟悉一下。您已经给出了一个消息链的完美示例,该消息链与它毫无业务可知的类过于亲密。

得墨忒耳法则: http ://en.wikipedia.org/wiki/Law_of_Demeter

原文由 Jerod Houghtelling 发布,翻译遵循 CC BY-SA 2.5 许可协议

如果您 无法 避免违反所选答案中所述的 Demeter 法则 (LoD),并且随着 Java 8 引入 Optional ,处理像您这样的获取链中的空值可能是最佳实践。

Optional 类型将使您能够连续传输多个映射操作(其中包含 get 调用)。空检查在后台自动处理。

例如,当对象未初始化时,不会执行 print() 操作,也不会抛出异常。我们在引擎盖下轻轻地处理这一切。初始化对象时,将进行打印。

 System.out.println("----- Not Initialized! -----");

Optional.ofNullable(new Outer())
        .map(out -> out.getNested())
        .map(nest -> nest.getInner())
        .map(in -> in.getFoo())
        .ifPresent(foo -> System.out.println("foo: " + foo)); //no print

System.out.println("----- Let's Initialize! -----");

Optional.ofNullable(new OuterInit())
        .map(out -> out.getNestedInit())
        .map(nest -> nest.getInnerInit())
        .map(in -> in.getFoo())
        .ifPresent(foo -> System.out.println("foo: " + foo)); //will print!

class Outer {
    Nested nested;
    Nested getNested() {
        return nested;
    }
}
class Nested {
    Inner inner;
    Inner getInner() {
        return inner;
    }
}
class Inner {
    String foo = "yeah!";
    String getFoo() {
        return foo;
    }
}

class OuterInit {
    NestedInit nested = new NestedInit();
    NestedInit getNestedInit() {
        return nested;
    }
}
class NestedInit {
    InnerInit inner = new InnerInit();
    InnerInit getInnerInit() {
        return inner;
    }
}
class InnerInit {
    String foo = "yeah!";
    String getFoo() {
        return foo;
    }
}

所以, 对于你的 getters 链,它看起来像这样:

 Optional.ofNullable(house)
        .map(house -> house.getFloor(0))
        .map(floorZero -> floorZero.getWall(WEST))
        .map(wallWest -> wallWest.getDoor())
        .map(door -> wallWest.getDoor())

它的返回类似于 Optional<Door> 这将使您的工作更加安全,而不必担心空异常。

原文由 Johnny 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题