Substituindo instrução get repetitiva por Java 8 Opcional

Eu tenho um caso de uso, onde aninhava classs e um object da class superior. Eu quero obter um valor que está no nível Nth. Estou usando getters repetidamente para conseguir isso para evitar o NPE. Exemplo de código (supondo que getters estejam lá)

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; } } 

Se eu tenho um object d da class D , e quero pegar o String a1 de A , o que estou fazendo é seguir:

 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; } 

Este repetitivo parece realmente feio. Como evito isso usando java8 Opcional?

EDIT: não posso modificar as classs acima. Suponha que esse object d seja retornado para mim como uma chamada de serviço. Estou exposto apenas a esses getters.

Use Optional com uma série de chamadas map() para um bom one-liner:

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

Se alguma coisa é null ao longo da cadeia, incluindo d , o orElse() será executado.

Embrulhe cada class aninhada em um opcional:

 Class A { String a1; } Class B { Optional a; } Class C { Optional b; } Class D { Optional c; } 

Em seguida, use flatMap e mapeie para operar nesses valores opcionais:

 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 

Você pode querer verificar o conceito de Monads . E se você estiver se sentindo aventureiro, o Scala está muito distante de Java .