2017-09-01 31 views
0

私のような匿名の内部クラスと列挙型を持っている:のJavaのenum匿名内部クラスと反射

public enum Status { 

    PRELIMINARY() { 
    @Override 
    boolean process() { 
     return true; 
    } 

    SUBMITTED() { 
    @Override 
    boolean process() { 
     return false; 
    } 

    abstract boolean process(); 

} 

私は同じようFoo.statusを設定するためにリフレクションを使用する必要が

public class Foo { 

    private Status status; 

    public void setStatus(Status status) { 
     this.status = status; 
    } 
} 

のようなモデルがあります:

private static <T> void setFieldValue(Foo instance, Class<?> klazz, Object value) { 
    try { 
     Class<?> aClass = value.getClass(); // Is Status$1 instead of Status 
     Method method = klazz.getDeclaredMethod(getSetterName('setStatus'), aClass); 
     method.invoke(instance, value); 
    } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { 
     if (!klazz.equals(Object.class)) { 
      setFieldValue(instance, klazz.getSuperclass(), fieldName, value); 
     } 
    } 
} 

これは、Statusに内部クラスがなく、単純なenumですが、上記のStatusクラスの場合はNoSuchMethodExceptionを投げます。これは、私のクラスのクラスがpackage.Statusの代わりにpackage.Status$1になるためです。

これには適切な回避策がありますか?

+0

あなたのサンプルコードには角括弧がないので、呼び出しに対応できるメソッドがないため、リフレクションの例は完全に無関係です。 – Dave

+0

Daveさん、ありがとうございました。私の問題をよりよく反映するようにコードを更新しました。 – pez

+0

[この回答](https://stackoverflow.com/a/45590933/2891664)が役に立ちます。しかし、私はなぜ正確にあなたがここで反射を使用しているのか疑問に思っています。あなたが事前に呼び出しているメソッドについて非常に多くを知っているようだからです。 – Radiodef

答えて

1

目的の方法を見つける方法を変更するだけで済みます。次のようなものは動作するはずです:

private static @Nullable Method findMethod(Class<?> klass, 
              final String methodName, 
              final Object... args) { 

    @Nullable Method candidate = null; 

    classSearch: 
    while (klass != null) { 

     // Check all the class' methods for a matching one. 
     methodSearch: 
     for (final Method method : klass.getDeclaredMethods()) { 
      if (!method.getName().equals(methodName)) continue; 

      final Class<?>[] parameterTypes = method.getParameterTypes(); 
      if (parameterTypes.length != args.length) continue; 

      // Check all parameters can come from the given args. 
      for (int i = 0; i < args.length; i++) { 
       if (!parameterTypes[i].isInstance(args[i])) continue methodSearch; 
      } 

      candidate = method; 
      break classSearch; 
     } 

     // No matching method, check super class. 
     klass = klass.getSuperclass(); 
    } 

    // May be 'null' if no match was found. 
    // Throw an Exception if this isn't a valid outcome in your case. 
    return candidate; 
} 

(それはnullない場合)(返さMethod.invokeを呼び出す)既存のコードでこれをチェーンあなたの望ましい結果を与える必要があります。

関連する問題