IllegalAccessError和IllegalAccessException之间的区别
考虑这对Throwable
:
IllegalAccessException
extends Exception
当应用程序尝试reflection性地创建实例(数组除外),设置或获取字段或调用方法时抛出,但当前正在执行的方法无法访问指定类,字段,方法或构造函数的定义。
IllegalAccessError
ext IncompatibleClassChangeError ext LinkageError ext Error
如果应用程序尝试访问或修改字段,或调用其无权访问的方法,则抛出该exception。
通常,编译器会捕获此错误; 如果类的定义不兼容地更改,则此错误只能在运行时发生。
问题
- 有人可以给出一个代码示例,其中每个被抛出?
- 名字的相似性是否意味着两者之间的关系,还是仅仅是纯粹的巧合?
- 还有其他
XXXError
和XXXException
组合吗? 这些对是如何相互关联的? - 如果您明确
try
在Exception/Error
对中catch
一个,您是否还应该catch
另一个?
有人可以给出一个代码示例,其中每个被抛出?
当您尝试使用reflection来调用方法或读取或写入Java可见性规则禁止的字段时,将引发IllegalAccessException
。
一致编译的Java代码不能抛出IllegalAccessError
。 例如,当您加载试图调用方法的类或读取或写入Java可见性规则禁止的另一个类中的字段时,就会发生这种情况。 这是编译器通常会阻止的,因此这意味着类有严重错误。 无论如何,这被认为是“错误”; 即不可恢复,类加载器将拒绝加载违规类。
名字的相似性是否意味着两者之间的关系,还是仅仅是纯粹的巧合?
两者之间有明确的关系。 不同之处在于两者发生的情况。
还有其他XXXError和XXXException组合吗? 这些对是如何相互关联的?
通过。 检查javadocs。
如果您明确尝试在exception/错误对中捕获一个,您是否还应该捕获另一个?
可能不是。 XXXError和XXXException通常在不同的情况下发生。 (这当然适用于reflection与类加载器。)
此外,作为一般规则,您不应尝试捕获并从Error
子类型中恢复。 将Error
与Exception
分开的关键是区分不可恢复和(可能)可恢复的exception。
在这种情况下,普通应用程序无法从IllegalAccessError
中恢复。 如果您尝试重复导致问题的类加载器操作,它将再次发生。
该描述已经解释了其中一些:当您使用reflection来访问字段或调用不可访问的方法时,抛出Exception
; 当你直接这样做时会抛出Error
(并且由于某种原因,编译器没有机会捕获它 – 例如当你有一个旧版本的类文件时,你正在尝试的字段或方法使用是私人的)。
Error
通常表示存在严重错误 – 软件中几乎肯定存在错误。 你永远不应该试图捕捉Error
。 如果您正在捕获XXXException
,则没有立即理由同时捕获XXXError
。 Error
的文档说:
Error是Throwable的子类,表示合理的应用程序不应该尝试捕获的严重问题。 大多数此类错误都是exception情况。 ThreadDeath错误,虽然是“正常”条件,但也是Error的子类,因为大多数应用程序不应该尝试捕获它。
一个方法不需要在其throws子句中声明在执行方法期间可能抛出但未捕获的任何Error类,因为这些错误是永远不应发生的exception情况。
生成IllegalAccessException
的示例:通过reflection,在类中查找私有方法并尝试调用它。
生成IllegalAccessError
的示例:创建两个类并将它们保存在两个源文件A.java
和B.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)。 所以我不知道他们是否以及何时被抛出。