【问题标题】:Enum's values() method access levelEnum 的 values() 方法访问级别
【发布时间】:2017-01-27 13:02:04
【问题描述】:

JLS 8 states 每个枚举类都有隐式声明的方法:

public static E[] values();

所以,按照规范,它是public

同时Class.getEnumConstantsShared()方法强行使其可访问:

            final Method values = getMethod("values");
            java.security.AccessController.doPrivileged(
                new java.security.PrivilegedAction<Void>() {
                    public Void run() {
                            values.setAccessible(true);
                            return null;
                        }
                    });
            @SuppressWarnings("unchecked")
            T[] temporaryConstants = (T[])values.invoke(null);

我想知道:这是什么意思?

【问题讨论】:

  • 可能与此评论相关:“当用户编造不符合枚举规范的类枚举类时,可能会发生这种情况。” grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
  • 哈,很好。怎么可能“编造”这样的班级? O_o
  • 在 Java 5 中引入枚举之前,创建自己的枚举等价物是一种常见做法(也是一种很好的做法):具有非公共构造函数的类和包含以下内容的公共静态常量该类的实例。例如TextAttributeFileChannel.MapModeDateFormat.Field
  • @VGR 这很有趣,但是那些类不包含 values() 方法。
  • @kaqqao 类不能直接扩展java.lang.Enum。它被编译器禁止。此外,Class.getEnumConstantsShared 通过调用方法Class.isEnum 可以防止非枚举类。

标签: java reflection enums


【解决方案1】:

简短回答:否则它将无法与公共 Enums 以外的任何东西一起使用

要访问MyEnum.values() 方法,该方法需要是公共的(它始终是)并且MyEnum 需要是public(或者它必须在同一个包中)。

从包java.lang 中的Class::getEnumConstantsShared() 访问该方法。因此,只要非公共 Enum 不在 java.lang getEnumConstantsShared() 中,就无法访​​问它。访问权由直接调用者决定,而不是由调用堆栈更高的人决定。 values.invoke(null) 的直接调用者是 java.lang.Class 中的代码,因此可访问性规则恰好适用于该上下文

如果您在某个包a

public class ValueGetter {
    public static Object[] getValues(Class<? extends Enum> enu) throws Exception {
        Method method = enu.getMethod("values");
        return (Object[]) method.invoke(null);
    }
}

并尝试在一个不同的b

中像这个sn-p一样访问它
public class EnumTest {
    enum MyEnum {
        LITERAL;
    }

    public static void main(String[] args) throws Exception {
        System.out.println(Arrays.toString(ValueGetter.getValues(MyEnum.class)));
    }
}

【讨论】:

  • 这是一个好点,我什至首先接受了你的回答。但随后我开始思考:仅在可以访问此枚举的同一上下文中执行对该方法的访问。此外,它可以在类本身内部访问。
  • 换句话说,只有当该枚举可访问且可见时,您才能在特定枚举上调用valueOf(...)
  • 其实和写Object values = MyEnum.class.getMethod("values").invoke(null);是一样的——不用强行写method.setAccessible(true)就可以了。
  • 对于可访问性,只有 直接调用者 与调用者的调用者无关。 values.invoke(null) 的直接调用者是 java.lang.Class 中的代码,因此可访问性规则恰好适用于该上下文。通过MyEnum.class.getEnumConstantsShared() 调用该方法并且该方法在该上下文中可见不再与可访问性相关。
  • @Andremoniy 完成 :-)。
猜你喜欢
  • 2012-11-19
  • 2019-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多