【问题标题】:Java enum anonymous inner class and reflectionJava枚举匿名内部类和反射
【发布时间】:2017-09-04 19:19:27
【问题描述】:

我有一个匿名内部类的枚举,例如:

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 like:

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

有什么好的解决方法吗?

【问题讨论】:

  • 不要太挑剔,但是您的示例代码缺少一些括号,并且您的反射示例似乎完全不相关,因为没有可以对应于调用的方法。
  • 感谢 Dave,我已更新代码以更好地反映我的问题。
  • This answer 可能会帮助您。但是,我会质疑您究竟为什么在这里使用反射,因为您似乎对您提前调用的方法了解很多。
  • 仅在这个高度简化的示例中......在野外,我正在生成一个 DynamicJasper 报告,用户可以在其中指定任意列。

标签: java reflection enums


【解决方案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))应该会给您想要的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多