2017-09-01 131 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))应该给你想要的结果。