2015-08-21 57 views
1

请尽量耐心等待,同时尽量提供尽可能多的信息。反思:枚举是公有的,那么该方法为什么IlegalAccessException即将到来?

我得到下面的异常在我的代码随机并不总是:

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$4 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())

这个问题并不总是来了...我已阅读,

的IllegalAccessException被抛出当应用程序试图 反射性地创建一个实例(除数组外),设置或获取一个 字段,或者调用一个方法,但是当前执行的方法不是 有权访问指定的类,字段,方法或构造函数的定义。

没有用户定义的类加载器。

但是,如果问题是因为构造函数CacheEnum是私有的,为什么它不总是来?如果不是那么它背后的问题是什么?我在这里错过了什么?

+0

为什么你的构造函数是私人的?因为在你的课堂上,没有可公开访问的构造函数。如果将构造函数更改为public,会发生什么情况?这个问题是否仍然存在? –

+0

你是什么意思_这个问题并不总是come_? – KDM

+1

类名'com.dclear.cmn.core.cache.CacheEnum $ 4'意味着你的枚举具有匿名类。可以显示完整的CacheEnum源代码? –

回答

2

当我们定义一个枚举类似如下:

public enum EnumTest { 

    ONE, TWO() { 
     @Override public String hello() { 
      return "World"; 
     } 
    }; 

    public String hello() { 
     return "Hello"; 
    } 
} 

Java的两个创建一个匿名类。我做了一个拆卸和它看起来像这样:

class snippet.EnumTest$1 extends snippet.EnumTest { 
    snippet.EnumTest$1(java.lang.String, int); 
    public java.lang.String hello(); 
} 

所以对于TWOClass被封装保护,当我们真正进入二的类反射不起作用。就像获取TWO的Enum对象并获取它的类一样。我怀疑你的情况就是这样。对于未覆盖该方法的所有情况,该方法正在工作,对于重写方法的情况,应该抛出异常。

我写了下面的测试来检查它。

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

如果您将两个类文件EnumTest和EnumReflect保留在同一个包中,则不会有任何异常。但是如果你把它们放在不同的包中,f2()会抛出你得到的异常。

+0

这似乎是一个非常好的接触,我会尝试研究更多这个现在确定之前释放此修复程序!谢谢.. – Dish

+0

但是,总是有例外吗? @KDM – Dish

+0

永远。从'f2()'。检查你是否只为覆盖你的'getSelectQuerySuffix'方法的枚举获取异常。框架中的代码路径可能是这样的,有时这些枚举可能会传递(参见'f1()')并且只会失败其他情况。如果在访问其他不重写'getSelectQuerySuffix'的枚举时遇到异常 - 这不是问题。 – KDM