Enum的values()方法访问级别

And*_*niy 12 java reflection enums

JLS 8 声明每个枚举类都隐式声明了方法:

public static E[] values();
Run Code Online (Sandbox Code Playgroud)

所以,它是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);
Run Code Online (Sandbox Code Playgroud)

我在想:这是什么意思?

k5_*_*k5_ 4

简短的回答:否则它不会与除了公共之外的任何东西一起工作Enums

要访问该方法MyEnum.values(),该方法需要是公共的(它总是如此)并且MyEnum需要是公共的public(或者它必须位于同一个包中)。

该方法是从Class::getEnumConstantsShared()包中访问的java.lang。因此,只要 none public 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

并尝试在不同的包中像此代码片段一样访问它b

public class EnumTest {
    enum MyEnum {
        LITERAL;
    }

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