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 .