嵌套对象最佳实践

时间:2011-03-09 16:18:01

标签: java object nested reference

引用嵌套对象的最佳做法是什么?

说我有以下内容:

class Outer {
 private InnerA innerA;
 //getters and setters
}

class InnerA {
  private InnerB innerB;
  //getters and setters
}

class InnerB {
  private String someString;
  //getters and setters
}

在我的控制器或服务类中,我需要检查InnerB类的someString String变量,以确保它不为null或不为空,所以我这样做:

if (getOuter().getInnerA().getInnerB().getSomeString() != null && !getOuter().getInnerA().getInnerB().getSomeString().equalsIgnoreCase("") {
  //do something
}

对我来说,这看起来很乱,如果嵌套对象本身为空,可能会出现问题。

我是否在父对象中为子对象检查null创建getter和setter?只是想知道在你的代码中,如果有的话和/或你们中的某些人做了什么最佳实践?

10 个答案:

答案 0 :(得分:7)

如果这些对象中的任何一个可以为null,那么在调用此对象的getter之前必须检查null,当然。

但是这种链接是缺乏封装的难闻气味(贫血对象只有数据,没有行为)。你违反了law of Demeter:不要和陌生人说话。

答案 1 :(得分:7)

您可以使用Apache Commons BeanUtils来浏览嵌套属性,如下所示:

将方法getSomeString()添加到您的Outer类并编写类似

的内容

PropertyUtils.getNestedProperty(this, "innerA.innerB.someString");

我不记得那个PropertyUtils类是否检查了null属性,但我会看Apache Commons BeanUtils site。

希望这有帮助!

答案 2 :(得分:4)

您有两种选择:

  1. 使用Null Object design pattern
  2. 等待 Java 7 Java 8 null safe operator。

答案 3 :(得分:4)

我建议您阅读Law of Demeter

答案 4 :(得分:1)

我不认为Outer的用户应该知道Outer.InnerA.InnerB.SomeString - 它被埋没到深层。如果不触及外部3级别的客户端,你就无法改变InnerB的实现 - 那么即使拥有内部类也有什么意义呢?像你所描述的情况是丑陋的,不应该出现。

我建议你首先考虑SomeString是属于InnerB还是InnerA或Outer。

现在假设您的层次结构是正确的,但SomeString具有Outer客户端所需的这个唯一属性(如果SomeString不是唯一的那样,层次结构肯定是错误的)。在这种情况下,Outer.getSomeString(),或者更好的是Outer.isSomeStringNullOrEmpty(),这样至少Outer的客户端不必知道InnerA和InnerB

PS。 someString.equalsIgnoreCase(“”)很贵,请不要使用它。更便宜的是someString.length()== 0

答案 5 :(得分:1)

它很乱,但如果你只需要在一个地方做,那么我可能会忍受它。否则,我会实现隐藏内部路径的Outer.getSomeString(),因为您的外部类是您作为界面公开的那个。

这也允许您处理其中一个中间内部类为空的情况,而不必在每次尝试访问someString时进行多次顺序检查。

答案 6 :(得分:1)

我的信念是你不应该通过外部类的方法暴露“内部 - 内部”成员,除非你为它们添加某种功能或不同的行为或者值对于使用外部类是“必不可少的” 。然而,这也是一个判断问题,可能会根据代码的用途和体系结构而有所不同。

另一方面,如果您希望长串调用的代码“不那么难看”,我建议在下一版本的Java中投票添加Elvis Operator项目硬币(我希望它有进入7: - ()。

答案 7 :(得分:1)

这是一个java限制。 你应该在父" OuterObject"中实现帮助器方法。如果它可以帮助您减少代码重复。

这个辅助方法对聚合其他对象的对象非常有用,只需要检查嵌套值是否存在。

代码:

getOuter().hasInnerB();

哪个会进行所有空检查。

从* .xsd生成的对象经常会出现此问题。 在复杂的xml结构中,通常会出现许多嵌套的可选节点。通常有趣的是最后一个节点。 然后最好编写辅助方法,如果节点存在可以重用,它将回答问题。

如果涉及到你的鳕鱼样本,我通常会写出类似的东西

if (hasSomeString(getOuter())) {
  //do something
}

答案 8 :(得分:1)

在 Java 8+ 中,这可以通过使用 Optional 来处理。

String value = Optional.ofNullable(outer).map(x -> x.getInnerA())
                      .map(x -> x.getInnerB()).map(x -> x.getSomeString())
                      .orElse(DEFAULT_VALUE);

答案 9 :(得分:0)

我写了一篇Java 8方法:

public class Helper {
    public static <IN, OUT> OUT returnNullOrCallFunction(IN o, Function<IN, OUT> f) {
        return o == null ? null : f.apply(o);
    }
}

现在你可以致电:

Helper.returnNullOrCallFunction(
        myObject.getSomeOtherObject(),
        SomeOtherObject::toString
);

如果myObject.getSomeOtherObject()null,则该方法会返回null,否则会调用myObject.getSomeOtherObject().toString()

这非常有用,如果你只需要深入一级。

对于多层次,它变得丑陋:

Helper.returnNullOrCallFunction(
        Helper.returnNullOrCallFunction(
                myObject.getSomeOtherObject(),
                SomeOtherObject::getAnotherObject
        ),
        AnotherObject::toString
);