私はちょうど同じものを探していました (私のコンテキスト: 自動的に作成された JAXB クラスの束、そしてどういうわけか私はこれらの長いデイジー チェーンを持っています.getFoo().getBar()...
。常に、途中で呼び出しの 1 つが null を返し、NPE を引き起こします。
しばらく前にいじり始めたものは、リフレクションに基づいています。これをよりきれいに、より効率的にできると確信しています (たとえば、リフレクションをキャッシュ._all
し、途中のメソッドがコレクションを返す場合、コレクションのすべての要素を自動的に反復するなどの「魔法の」メソッドを定義します)。 )。きれいではありませんが、おそらく誰かが私たちにもっと良いものがあるかどうか教えてくれるでしょう:
/**
* Using {@link java.lang.reflect.Method}, apply the given methods (in daisy-chain fashion)
* to the array of Objects x.
*
* <p>For example, imagine that you'd like to express:
*
* <pre><code>
* Fubar[] out = new Fubar[x.length];
* for (int i=0; {@code i<x.length}; i++) {
* out[i] = x[i].getFoo().getBar().getFubar();
* }
* </code></pre>
*
* Unfortunately, the correct code that checks for nulls at every level of the
* daisy-chain becomes a bit convoluted.
*
* <p>So instead, this method does it all (checks included) in one call:
* <pre><code>
* Fubar[] out = apply(new Fubar[0], x, "getFoo", "getBar", "getFubar");
* </code></pre>
*
* <p>The cost, of course, is that it uses Reflection, which is slower than
* direct calls to the methods.
* @param type the type of the expected result
* @param x the array of Objects
* @param methods the methods to apply
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T[] apply(T[] type, Object[] x, String...methods) {
int n = x.length;
try {
for (String methodName : methods) {
Object[] out = new Object[n];
for (int i=0; i<n; i++) {
Object o = x[i];
if (o != null) {
Method method = o.getClass().getMethod(methodName);
Object sub = method.invoke(o);
out[i] = sub;
}
}
x = out;
}
T[] result = (T[])Array.newInstance(type.getClass().getComponentType(), n);
for (int i=0; i<n; i++) {
result[i] = (T)x[i];
}
return result;
} catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}