Si vous ne souhaitez pas refactoriser le code et que vous pouvez utiliser Java 8, il est possible d'utiliser des références de méthode.
Une simple démo d'abord (excusez les classes internes statiques)
public class JavaApplication14
{
static class Baz
{
private final int _int;
public Baz(int value){ _int = value; }
public int getInt(){ return _int; }
}
static class Bar
{
private final Baz _baz;
public Bar(Baz baz){ _baz = baz; }
public Baz getBar(){ return _baz; }
}
static class Foo
{
private final Bar _bar;
public Foo(Bar bar){ _bar = bar; }
public Bar getBar(){ return _bar; }
}
static class WSObject
{
private final Foo _foo;
public WSObject(Foo foo){ _foo = foo; }
public Foo getFoo(){ return _foo; }
}
interface Getter<T, R>
{
R get(T value);
}
static class GetterResult<R>
{
public R result;
public int lastIndex;
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
WSObject wsObject = new WSObject(new Foo(new Bar(new Baz(241))));
WSObject wsObjectNull = new WSObject(new Foo(null));
GetterResult<Integer> intResult
= getterChain(wsObject, WSObject::getFoo, Foo::getBar, Bar::getBar, Baz::getInt);
GetterResult<Integer> intResult2
= getterChain(wsObjectNull, WSObject::getFoo, Foo::getBar, Bar::getBar, Baz::getInt);
System.out.println(intResult.result);
System.out.println(intResult.lastIndex);
System.out.println();
System.out.println(intResult2.result);
System.out.println(intResult2.lastIndex);
// TODO code application logic here
}
public static <R, V1, V2, V3, V4> GetterResult<R>
getterChain(V1 value, Getter<V1, V2> g1, Getter<V2, V3> g2, Getter<V3, V4> g3, Getter<V4, R> g4)
{
GetterResult result = new GetterResult<>();
Object tmp = value;
if (tmp == null)
return result;
tmp = g1.get((V1)tmp);
result.lastIndex++;
if (tmp == null)
return result;
tmp = g2.get((V2)tmp);
result.lastIndex++;
if (tmp == null)
return result;
tmp = g3.get((V3)tmp);
result.lastIndex++;
if (tmp == null)
return result;
tmp = g4.get((V4)tmp);
result.lastIndex++;
result.result = (R)tmp;
return result;
}
}
Production
241
4
nul
2
L'interface Getter
n'est qu'une interface fonctionnelle, vous pouvez utiliser n'importe quel équivalent.
GetterResult
class, les accesseurs supprimés pour plus de clarté, contiennent le résultat de la chaîne getter, le cas échéant, ou l'index du dernier getter appelé.
La méthode getterChain
est un morceau de code simple et standard, qui peut être généré automatiquement (ou manuellement si nécessaire).
J'ai structuré le code pour que le bloc répétitif soit évident.
Ce n'est pas une solution parfaite car vous devez toujours définir une surcharge de getterChain
par nombre de getters.
Je refactoriserais le code à la place, mais si vous ne pouvez pas et que vous vous trouvez en utilisant souvent de longues chaînes getter, vous pouvez souvent envisager de créer une classe avec des surcharges qui prennent de 2 à, disons, 10 getters.
null
vérifications ne me dérangeraient pas autant, carwsObject.getFoo().getBar().getBaz().getInt()
c'est déjà une odeur de code. Lisez ce qu'est la «loi de Demeter» et préférez refactoriser votre code en conséquence. Ensuite, le problème avec lesnull
chèques disparaîtra également. Et pensez à utiliserOptional
.