嵌套对象最佳实践

发布于 2024-10-21 05:12:21 字数 663 浏览 1 评论 0原文

引用嵌套对象的最佳实践是什么?

假设我有以下内容:

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
}

对我来说,这看起来很混乱并且可能有问题如果嵌套对象本身为空。

我是否需要在父对象中创建 getter 和 setter 以便子对象检查 null ?只是想知道最佳实践是什么(如果有)和/或你们中的一些人在代码中做了什么?

What is the best practice for referencing nested objects?

Let's say I have the following:

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

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

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

and in my controller or service class I need to check the someString String variable of the InnerB class to make sure it is not null or not empty so I do this:

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

To me this looks messy and could have issues if the nested objects themselves are null.

Do I need to create getters and setters in the parent objects for the child objects checking for null? Just wondering what the best practice is if any and/or what some of you do in your code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

深居我梦 2024-10-28 05:12:22

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

但这种链接是缺乏封装的坏味道(贫乏的对象只有数据,没有行为)。你违反了德米特法则:不要和陌生人说话。

If any of those objects can be null, then you have to check for null before calling a getter on this object, of course.

But this kind of chaining is a bad smell of a lack of encapsulation (anemic objects having just data, and no behavior). You're violating the law of Demeter : don't talk to strangers.

鹊巢 2024-10-28 05:12:22

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

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

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

我不记得 PropertyUtils 类是否检查 null 属性,但我会查看 Apache Commons BeanUtils 站点。

希望这有帮助!

You can use Apache Commons BeanUtils to navigate through your nested properties like this:

Add method getSomeString() to your Outer class and write something like

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

I can't remember if that PropertyUtils class check null properties, but I would look Apache Commons BeanUtils site.

Hope this helps!

夜吻♂芭芘 2024-10-28 05:12:22

我建议您阅读德墨忒尔定律

I would recommend reading up on the Law of Demeter.

裂开嘴轻声笑有多痛 2024-10-28 05:12:22

您有两个选择:

  1. 使用空对象设计模式
  2. 等待Java 7 Java 8 null 安全运算符。

You have two options:

  1. Use Null Object design pattern
  2. Wait for Java 7 Java 8 null safe operator.
一页 2024-10-28 05:12:22

在 Java 8+ 中,可以使用 <代码>可选

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

In Java 8+, this can be handled by using Optional.

String value = Optional.ofNullable(outer).map(x -> x.getInnerA())
                      .map(x -> x.getInnerB()).map(x -> x.getSomeString())
                      .orElse(DEFAULT_VALUE);
简美 2024-10-28 05:12:22

我认为 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

I don't think users of Outer should have knowledge of Outer.InnerA.InnerB.SomeString - it's buried to deep. You can't change implementation of InnerB without touching clients of Outer 3 levels separated - so what's the point of even having inner classes? Situations like you're describing are ugly and shouldn't arise.

I'd recommend you first consider whether SomeString belongs in InnerB or InnerA or Outer.

Now suppose your hierarchy is correct, yet SomeString has this unique property of being required by clients of Outer (if SomeString is not unique that way, hierarchy is definitely wrong). In this case, Outer.getSomeString(), or better yet, Outer.isSomeStringNullOrEmpty(), so that at least clients of Outer don't have to know about InnerA and InnerB

PS. someString.equalsIgnoreCase("") is expensive, don't use that. Much cheaper is someString.length() == 0

硪扪都還晓 2024-10-28 05:12:22

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

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

It's messy, but if you only had to do it in one place then I might live with it. Otherwise, I'd implement a Outer.getSomeString() that hides the internal path, since your Outer class is the one you're exposing as your interface.

This also allows you to deal with a case where one of the intermediary inner classes is null, without having to do a number of sequential checks each time you try to access someString.

归途 2024-10-28 05:12:22

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

附带说明一下,如果您希望一长串调用的代码“不那么难看”,我建议投票支持添加 Elvis Operator 用于下一版本 Java 中的项目币(我希望它已成为 7 :-()。

My belief is that you should not expose "inner-inner" members through methods of the outer class unless you are adding some sort of functionality or different behaviour to them or the value is "essential" to the use of the outer class. However this is also a matter of judgement and can vary depending on the use and architecture of your code.

On a side note if you want the code for a long string of invocations to be "less ugly" I suggest voting for addition of the Elvis Operator for project coin in the next version of Java (I wish it had made it into 7 :-().

起风了 2024-10-28 05:12:22

这是java的限制。
如果有助于减少代码重复,您应该在父“OuterObject”中实现辅助方法。

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

代码:

getOuter().hasInnerB();

它将执行所有空检查。

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

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

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

This is a java limitation.
You should implement helper methods in the parent "OuterObject" if it helps you to reduce code duplication.

This helper methods are useful for object which are aggregating other object and you need to check only if the nested value exists.

Code:

getOuter().hasInnerB();

Which would do all the null checks.

This problem occurs often with objects generated from *.xsd.
In a complicated xml structure it happens often that there a many nested optional nodes. And what usually is interesting is the last node.
Then its better to write helper methods which will answer the questions if node exists for reuse.

If it comes up to your cod sample i usually write something like that

if (hasSomeString(getOuter())) {
  //do something
}
忆梦 2024-10-28 05:12:22

我编写了一个 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
);

I've written a Java 8 Method:

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

Now you can call:

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

If myObject.getSomeOtherObject() is null the method will return null, else it will call myObject.getSomeOtherObject().toString().

That's pretty useful, if you just have to go one level deeper.

For multi level, it gets ugly:

Helper.returnNullOrCallFunction(
        Helper.returnNullOrCallFunction(
                myObject.getSomeOtherObject(),
                SomeOtherObject::getAnotherObject
        ),
        AnotherObject::toString
);
眼眸 2024-10-28 05:12:22

如果您已经在使用 Spring,请考虑使用 BeanWrapper 或 ConfigurablePropertyAccessor:

BeanWrapper propertyAccessor = PropertyAccessorFactory.forBeanPropertyAccess(outer);
String someString = propertyAccessor.getPropertyValue("innerA.innerB.someString");

如果任何嵌套属性为 null,则 getPropertyValue 会抛出异常。代码>.您可以捕获该异常并返回您想要的任何内容。

If you are already using Spring, consider BeanWrapper or ConfigurablePropertyAccessor:

BeanWrapper propertyAccessor = PropertyAccessorFactory.forBeanPropertyAccess(outer);
String someString = propertyAccessor.getPropertyValue("innerA.innerB.someString");

getPropertyValue throws an Exception if any of the nested properties is null. you can catch that Exception and return whatever you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文