Уровень доступа к методу Enum()

JLS 8 указывает, что каждый класс перечисления имеет неявно объявленный метод:

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);

Мне интересно: какой смысл?

Ответ 1

Короткий ответ: иначе он не будет работать ни с чем, кроме публичного Enums

Чтобы получить доступ к методу MyEnum.values(), этот метод должен быть общедоступным (он всегда есть), а MyEnum должен быть public (или он должен находиться в одном пакете).

Доступ к методу осуществляется из Class::getEnumConstantsShared() в пакете java.lang. Так что пока ни один публичный 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

public class EnumTest {
    enum MyEnum {
        LITERAL;
    }

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