2017-09-01 70 views
0

我有一個枚舉匿名內部類,如:的Java枚舉匿名內部類和反射

public enum Status { 

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

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

    abstract boolean process(); 

} 

我有一個像

public class Foo { 

    private Status status; 

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

我需要使用反射來設置Foo.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不包含內部類並且是一個簡單枚舉,但是對於上面的Status類,它會拋出一個NoSuchMethodException。這是因爲我的價值等級是package.Status$1而不是package.Status

有沒有很好的解決這個問題?

+0

不要太挑剔,但您的示例代碼缺少一些括號,您的反射示例看起來完全不相關,因爲沒有可能對應於調用的方法。 – Dave

+0

感謝戴夫,我已更新我的代碼以更好地反映我的問題。 – pez

+0

[This answer](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; 
} 

與您現有的代碼鏈接本(調用返回的Method.invoke(如果它不是null))應該給你想要的結果。