用Java 8替换重复的get语句可选

AKB*_*AKB 5 java optional

我有一个用例,我有嵌套类和顶级类的对象.我想得到一个在第N级的值.我正在重复使用getter来实现这一点以避免NPE.示例代码(假设有吸气剂)

class A {
    String a1;
    String getA1() {
        return a1;
    }
}

class B {
    A a;
    A getA() {
        return a;
    }
}

class C {
    B b;
    B getB() {
        return b;
    }
}

class D {
    C c;
    C getC() {
        return c;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我有一个对象dD,并希望得到String a1A,我在做什么是以下几点:

String getAValue(D d) {
    String aValue = null;
    if(d != null && d.getC() != null && d.getC().getB() != null && d.getC().getB().getA() != null) {
        aValue = d.getC().getB().getA().getA1();
    }
    return aValue;
}
Run Code Online (Sandbox Code Playgroud)

这个重复的看起来真的很难看.如何使用java8 Optional来避免它?

编辑:我不能修改上面的类.假设这个d对象作为服务调用返回给我.我只接触过这些吸气剂.

Boh*_*ian 6

使用Optional一系列map()调用一个漂亮的单行:

String getAValue(D d) {
   return Optional.ofNullable(d)
       .map(D::getC).map(C::getB).map(B::getA).map(A::getA1).orElse(null);
}
Run Code Online (Sandbox Code Playgroud)

如果null链上有任何东西,包括d它自己,那么orElse()就会执行.


jhn*_*jhn 2

将每个嵌套类包装在Optional中:

Class A {
    String a1;
}
Class B {
    Optional<A> a;
}
Class C {
    Optional<B> b;
}
Class D {
    Optional<C> c;
}
Run Code Online (Sandbox Code Playgroud)

然后使用 flatMap 和 map 对这些可选值进行操作:

String a1 = d.flatMap(D::getC) // flatMap operates on Optional
             .flatMap(C::getB) // flatMap also returns an Optional
             .flatMap(B::getA) // that's why you can keep calling .flatMap()
             .map(A::getA1)    // unwrap the value of a1, if any
             .orElse("Something went wrong.") // in case anything fails
Run Code Online (Sandbox Code Playgroud)

您可能想查看Monad的概念。如果您喜欢冒险,Scala 与 Java 相去甚远