反思:枚举是 Public 方法也是 Public 那么为什么会出现 IlegalAccessException?
Reflection : The Enum is Public so is The method then Why IlegalAccessException Is Coming?
请耐心等待我尽量提供尽可能多的信息。
我在我的代码中随机出现异常,但并非总是如此:
ERROR CACHE-SELECT 2015-08-20 11:19:00,822 nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 'table.selectQuerySuffix'. Cause: org.apache.ibatis.ognl.OgnlException: selectQuerySuffix [java.lang.IllegalAccessException: Class org.apache.ibatis.ognl.OgnlRuntime can not access a member of class com.dclear.cmn.core.cache.CacheEnum with modifiers "public"] -
定义的枚举如下:
public enum CacheEnum {
TABLE_NAME() {
@Override
public String getSelectQuerySuffix() {
return "";
}
};
private CacheEnum() {
//some assignment
}
public enum Schema {
//SCHEMAS DEFINED
}
public enum SchemaName {
// NAMES
}
public String getSelectQuerySuffix() {
return "";
}
public enum ColumnEnum {
//SOME VALUES
ColumnEnum() {
}
}
public enum CacheTableSequence {
//SQs
}
}
'table.selectQuerySuffix'定义在MyBatis文件中放置查询后缀。并且在运行时它作为“”传递(参考覆盖方法 getSelectQuerySuffix())
这个问题并不总是会出现...我已经阅读
An IllegalAccessException is thrown when an application tries to
reflectively create an instance (other than an array), set or get a
field, or invoke a method, but the currently executing method does not
have access to the definition of the specified class, field, method or
constructor.
There are no user-defined class loaders.
但是如果问题是因为构造函数 CacheEnum 是私有的,为什么它并不总是出现?如果不是那么它背后的问题是什么?我在这里错过了什么?
当我们定义一个 Enum 如下:
public enum EnumTest {
ONE, TWO() {
@Override public String hello() {
return "World";
}
};
public String hello() {
return "Hello";
}
}
Java 为 TWO 创建匿名 class。我对其进行了反汇编,它看起来像这样:
class snippet.EnumTest extends snippet.EnumTest {
snippet.EnumTest(java.lang.String, int);
public java.lang.String hello();
}
所以 TWO
的 Class
是包保护的,当我们实际访问 TWO 的 class 时反射不起作用。就像获取 TWO 的 Enum 对象并获取其 class 一样。我怀疑这就是你的情况。对于所有未覆盖该方法的情况,它都在工作,对于那些覆盖该方法的情况,它应该抛出异常。
我写了下面的测试来检查它。
public class EmumReflect {
public static void main(String[] args) throws Exception {
f1();
f2();
}
public static void f1() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException,
InvocationTargetException {
Class<?> forName = Class.forName("snippet.EnumTest");
Object fOne = forName.getField("ONE").get(null);
Object fTwo = forName.getField("TWO").get(null);
Method method = forName.getMethod("hello");
System.out.println(method.invoke(fOne));
System.out.println(method.invoke(fTwo));
}
public static void f2() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException,
InvocationTargetException {
Class<?> forNamex = Class.forName("snippet.EnumTest");
Object fTwo = forNamex.getField("TWO").get(null);
Class<?> forName = fTwo.getClass();
Method method = forName.getMethod("hello");
System.out.println(method.invoke(fTwo));
}
}
如果将 class 文件 EnumTest 和 EnumReflect 保存在同一个包中,则不会出现任何异常。但是,如果您将它们放在不同的包中,f2() 会抛出您遇到的相同异常。
请耐心等待我尽量提供尽可能多的信息。
我在我的代码中随机出现异常,但并非总是如此:
ERROR CACHE-SELECT 2015-08-20 11:19:00,822 nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 'table.selectQuerySuffix'. Cause: org.apache.ibatis.ognl.OgnlException: selectQuerySuffix [java.lang.IllegalAccessException: Class org.apache.ibatis.ognl.OgnlRuntime can not access a member of class com.dclear.cmn.core.cache.CacheEnum with modifiers "public"] -
定义的枚举如下:
public enum CacheEnum {
TABLE_NAME() {
@Override
public String getSelectQuerySuffix() {
return "";
}
};
private CacheEnum() {
//some assignment
}
public enum Schema {
//SCHEMAS DEFINED
}
public enum SchemaName {
// NAMES
}
public String getSelectQuerySuffix() {
return "";
}
public enum ColumnEnum {
//SOME VALUES
ColumnEnum() {
}
}
public enum CacheTableSequence {
//SQs
}
}
'table.selectQuerySuffix'定义在MyBatis文件中放置查询后缀。并且在运行时它作为“”传递(参考覆盖方法 getSelectQuerySuffix())
这个问题并不总是会出现...我已经阅读
An IllegalAccessException is thrown when an application tries to reflectively create an instance (other than an array), set or get a field, or invoke a method, but the currently executing method does not have access to the definition of the specified class, field, method or constructor.
There are no user-defined class loaders.
但是如果问题是因为构造函数 CacheEnum 是私有的,为什么它并不总是出现?如果不是那么它背后的问题是什么?我在这里错过了什么?
当我们定义一个 Enum 如下:
public enum EnumTest {
ONE, TWO() {
@Override public String hello() {
return "World";
}
};
public String hello() {
return "Hello";
}
}
Java 为 TWO 创建匿名 class。我对其进行了反汇编,它看起来像这样:
class snippet.EnumTest extends snippet.EnumTest {
snippet.EnumTest(java.lang.String, int);
public java.lang.String hello();
}
所以 TWO
的 Class
是包保护的,当我们实际访问 TWO 的 class 时反射不起作用。就像获取 TWO 的 Enum 对象并获取其 class 一样。我怀疑这就是你的情况。对于所有未覆盖该方法的情况,它都在工作,对于那些覆盖该方法的情况,它应该抛出异常。
我写了下面的测试来检查它。
public class EmumReflect {
public static void main(String[] args) throws Exception {
f1();
f2();
}
public static void f1() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException,
InvocationTargetException {
Class<?> forName = Class.forName("snippet.EnumTest");
Object fOne = forName.getField("ONE").get(null);
Object fTwo = forName.getField("TWO").get(null);
Method method = forName.getMethod("hello");
System.out.println(method.invoke(fOne));
System.out.println(method.invoke(fTwo));
}
public static void f2() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException, NoSuchMethodException,
InvocationTargetException {
Class<?> forNamex = Class.forName("snippet.EnumTest");
Object fTwo = forNamex.getField("TWO").get(null);
Class<?> forName = fTwo.getClass();
Method method = forName.getMethod("hello");
System.out.println(method.invoke(fTwo));
}
}
如果将 class 文件 EnumTest 和 EnumReflect 保存在同一个包中,则不会出现任何异常。但是,如果您将它们放在不同的包中,f2() 会抛出您遇到的相同异常。