IllegalAccessError和IllegalAccessException之间的区别

考虑这对Throwable

IllegalAccessException extends Exception

当应用程序尝试reflection性地创建实例(数组除外),设置或获取字段或调用方法时抛出,但当前正在执行的方法无法访问指定类,字段,方法或构造函数的定义。

IllegalAccessError ext IncompatibleClassChangeError ext LinkageError ext Error

如果应用程序尝试访问或修改字段,或调用其无权访问的方法,则抛出该exception。

通常,编译器会捕获此错误; 如果类的定义不兼容地更改,则此错误只能在运行时发生。

问题

  • 有人可以给出一个代码示例,其中每个被抛出?
  • 名字的相似性是否意味着两者之间的关系,还是仅仅是纯粹的巧合?
  • 还有其他XXXErrorXXXException组合吗? 这些对是如何相互关联的?
  • 如果您明确tryException/Error对中catch一个,您是否还应该catch另一个?

有人可以给出一个代码示例,其中每个被抛出?

当您尝试使用reflection来调用方法或读取或写入Java可见性规则禁止的字段时,将引发IllegalAccessException

一致编译的Java代码不能抛出IllegalAccessError 。 例如,当您加载试图调用方法的类或读取或写入Java可见性规则禁止的另一个类中的字段时,就会发生这种情况。 这是编译器通常会阻止的,因此这意味着类有严重错误。 无论如何,这被认为是“错误”; 即不可恢复,类加载器将拒绝加载违规类。

名字的相似性是否意味着两者之间的关系,还是仅仅是纯粹的巧合?

两者之间有明确的关系。 不同之处在于两者发生的情况。

还有其他XXXError和XXXException组合吗? 这些对是如何相互关联的?

通过。 检查javadocs。

如果您明确尝试在exception/错误对中捕获一个,您是否还应该捕获另一个?

可能不是。 XXXError和XXXException通常在不同的情况下发生。 (这当然适用于reflection与类加载器。)

此外,作为一般规则,您不应尝试捕获并从Error子类型中恢复。 将ErrorException分开的关键是区分不可恢复和(可能)可恢复的exception。

在这种情况下,普通应用程序无法从IllegalAccessError中恢复。 如果您尝试重复导致问题的类加载器操作,它将再次发生。

该描述已经解释了其中一些:当您使用reflection来访问字段或调用不可访问的方法时,抛出Exception ; 当你直接这样做时会抛出Error (并且由于某种原因,编译器没有机会捕获它 – 例如当你有一个旧版本的类文件时,你正在尝试的字段或方法使用是私人的)。

Error通常表示存在严重错误 – 软件中几乎肯定存在错误。 你永远不应该试图捕捉Error 。 如果您正在捕获XXXException ,则没有立即理由同时捕获XXXErrorError的文档说:

Error是Throwable的子类,表示合理的应用程序不应该尝试捕获的严重问题。 大多数此类错误都是exception情况。 ThreadDeath错误,虽然是“正常”条件,但也是Error的子类,因为大多数应用程序不应该尝试捕获它。

一个方法不需要在其throws子句中声明在执行方法期间可能抛出但未捕获的任何Error类,因为这些错误是永远不应发生的exception情况。

生成IllegalAccessException的示例:通过reflection,在类中查找私有方法并尝试调用它。

生成IllegalAccessError的示例:创建两个类并将它们保存在两个源文件A.javaB.java 。 在类A ,创建一个公共方法,在类B ,调用该方法。 编译源文件。 现在,编辑A.java并将该方法A.java私有,并仅重新编译A.java (而不是B.java )。 现在再试一次; B将尝试调用该方法并抛出IllegalAccessError

还有其他一对XXXException / XXXError似乎相关,但它们并不总是具有完全匹配的名称; 例如ClassNotFoundException / NoClassDefFoundError

java.lang有几对exception/错误,以下所有内容都涉及reflection与直接用法:

 IllegalAccessException / IllegalAccessError InstantiationException / InstantiationError ClassNotFoundException / NoClassDefFoundError NoSuchFieldException / NoSuchFieldError NoSuchMethodException / NoSuchMethodError 

其他例子是:

 java.awt.AWTException / java.awt.AWTError java.io.IOException / java.io.IOError 

到目前为止,我不知道存在这两个错误,并且它们没有从Javadoc中的其他类引用(1.6)。 所以我不知道他们是否以及何时被抛出。