引用嵌套对象的最佳做法是什么?
说我有以下内容:
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?只是想知道在你的代码中,如果有的话和/或你们中的某些人做了什么最佳实践?
答案 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)
您有两种选择:
答案 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
);