如何避免嵌套的空值检查

3

我希望通过API检索类中的字段。是的,我知道这违反了Demeter法则,但我没有其他选择。

例如:

getClassA().getClassB().getClassC().getClassD().getAccountId();

因为空指针检查是一种糟糕的代码坏味道,所以我提出了以下代码:

try{
getClassA().getClassB().getClassC().getClassD().getAccountId();
}catch(NullPointerException ex){
 S.O.P("Null Found");
}

或者

ClassA a = getClassA();
if(a!=null){
ClassB b = a.getClassB();
So on.....
}

我的问题是,哪种方法更好,是上面提到的方法还是显式检索每个类并检查空值并进入下一级。这违反了Demeter法则。

2
请看这里:http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html 这篇文章详细解释了你的问题。 - aw-think
如果你遇到这样的问题,我会说你的架构/设计不正确。正如你自己所说,你违反了洛德米特法则,这可能会解决这个问题。你能提供一下你正在尝试做什么的更广泛的背景吗? - Jaroslaw Pawlak
@NwDx 这里使用 Optional 是没有帮助的,因为这将会是一系列嵌套的 isPresent() 调用。 - Jaroslaw Pawlak
@JaroslawPawlak:不,你可以调用最新的get方法并在那里进行测试。 - aw-think
@user2387280,Google的Guava库也提供了Optional类。 - Jaroslaw Pawlak
显示剩余2条评论
2个回答

2

空对象设计模式是一种在Java 8中通过Optional类被吸收的方式,这意味着您拥有一个包装器,其中包含数据或空数据。

它类似于

             MyObject
      RealObject    NullObject

在这里,你需要传递NullObject而不是null,NullObject提供了与MyObject相同的接口(可以是具体/抽象/接口类)


感谢@SMA的回复,我在发布这个问题之前已经检查过了,但那是针对Java8的,而我正在寻找Java 7。 - user2387280
在这里,我正在使用API,所以我无法要求他们传递空的嵌套对象。 - user2387280
尝试使用我所说的Null Object设计模式的相同概念。请查看它遵循的类层次结构(我在上面的答案中给了一个提示)。 - SMA
@user2387280,你的项目应该与你无法更改的代码隔离开来。创建自己的隔离层,仅公开你正在使用的第三方API的必要部分。如果你正在使用TDD,这应该有集成测试。 - Jaroslaw Pawlak
你看到我选项1中的问题了吗?我正在处理异常。 - user2387280
但是你能获取accountId并且在没有它的情况下执行进一步的操作吗?同时,考虑每个语句,你是否要做这样的事情,例如 try { } catch... - SMA

2

这需要Java 8,你说得没错。我认为在Guava中它的功能会类似。

public class OptionalTest {

  public static void main(String[] args) {
    A a = new A();
    Optional<A> opa = Optional.ofNullable(a);
    int accid = opa.map(A::getClassB).map(A.B::getClassC).map(A.B.C::getClassD).map(A.B.C.D::getAccountID).orElse(-1);

    if (accid > -1) {
      System.out.println("The account id is: " + accid);
    } else {
      System.out.println("One of them was null. Please play with commenting.");
    }
  }

    static class A {
      B b = new B();
      //B b = null;
      B getClassB() {
        return b;
      }

      static class B {
        //C c = new C();
        C c = null;
        C getClassC() {
          return c;
        }

          static class C {
            D d = new D();
            //D d = null;
            D getClassD() {
              return d;
            }

              static class D {
                private final int accountId = 2;
                int getAccountID() {
                  return accountId;
                }
              }
          }
      }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接