JLS 8 states that each enum class has implicitly declared method:
public static E[] values();
So, it is public
by specification.
At the same time Class.getEnumConstantsShared()
method forcibly makes it accessible:
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);
I'm wondering: what's the sense?
Short answer: otherwise it would not work with anything but public Enums
To access the method MyEnum.values()
, the method needs to be public (it always is) and MyEnum
needs to be public
(or it must be in the same package).
The method is accessed from the Class::getEnumConstantsShared()
in the package java.lang
. So as long as the none public Enum is not in java.lang
getEnumConstantsShared()
will not have access to it. Access is determined by the direct caller not by somebody higher up the call stack. The direct caller of values.invoke(null)
is the code in java.lang.Class
so the accessibility rules apply to exactly that context
That can be easily verified (following code will not work) if you create a static method in some package a
public class ValueGetter {
public static Object[] getValues(Class<? extends Enum> enu) throws Exception {
Method method = enu.getMethod("values");
return (Object[]) method.invoke(null);
}
}
And try to access it like this snippet in a different package b
public class EnumTest {
enum MyEnum {
LITERAL;
}
public static void main(String[] args) throws Exception {
System.out.println(Arrays.toString(ValueGetter.getValues(MyEnum.class)));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With