1. 概述
在这个快速教程中,我们将讨论java.lang.IllegalAccessError
我们将研究一些关于何时抛出以及如何避免它的示例。
2. IllegalAccessError
当应用程序尝试访问字段或调用不可访问的方法时,会IllegalAccessError
编译器会捕获此类非法调用,但我们仍可能在运行时IllegalAccessError
首先,让我们观察一下IllegalAccessError:
java.lang.Object |_java.lang.Throwable |_java.lang.Error |_java.lang.LinkageError |_java.lang.IncompatibleClassChangeError |_java.lang.IllegalAccessError
它的父类是IncompatibleClassChangeError.因此,此错误的原因是应用程序中一个或多个类定义的不兼容更改。
简而言之,运行时类的版本与其编译时所针对的版本不同。
3. 这个错误怎么会发生?
让我们用一个简单的程序来理解这一点:
public class Class1 { public void bar() { System.out.println("SUCCESS"); } } public class Class2 { public void foo() { Class1 c1 = new Class1(); c1.bar(); } }
在运行时,上面的代码调用Class1. bar()到现在为止还挺好。
现在,让我们将bar()的访问修饰符更新为private并独立编译它。
接下来,将Class1 (the .的先前定义(.class 文件)替换为新编译的版本并重新运行程序:
java.lang.IllegalAccessError: class Class2 tried to access private method Class1.bar()
上述例外是不言自明的。方法bar()现在在Class1. private显然,访问是非法的。
4. IllegalAccessError
在行动
4.1.图书馆更新
考虑一个在编译时使用库的应用程序,并且在运行时在类路径中也可用。
库所有者将公开可用的方法更新为私有,重建它,但忘记更新此更改的其他方。
此外,在执行时,当应用程序调用此方法(假设公共访问)时,它会遇到IllegalAccessError.
4.2 接口默认方法
接口中默认方法的滥用是导致此错误的另一个原因。
考虑以下接口和类定义:
interface Baeldung { public default void foobar() { System.out.println("This is a default method."); } } class Super { private void foobar() { System.out.println("Super class method foobar"); } }
另外,让我们扩展Super并实现Baeldung:
class MySubClass extends Super implements Baeldung {}
最后,让我们通过实例化MySubClass: foobar()
new MySubClass().foobar();
方法foobar() Super是私有的,在Baeldung. default因此,它可以在 MySubClass 的层次结构中MySubClass.
因此,编译器不会抱怨,但在运行时,我们得到一个错误:
java.lang.IllegalAccessError: class IllegalAccessErrorExample tried to access private method 'void Super.foobar()'
在执行期间,超类方法声明始终优先于接口默认方法。
从技术上讲, Super foobar ,但它是私有的。毫无疑问,会抛出IllegalAccessError
5. 如何避免?
准确地说,如果我们遇到IllegalAccessError ,我们应该主要寻找类定义中关于访问修饰符的变化。
其次,我们应该验证被私有访问修饰符覆盖的接口默认方法。
将类级别的方法设为公开即可。
六,结论
总而言之,编译器将解决大多数非法方法调用。如果我们仍然遇到IllegalAccesError ,我们需要查看类定义的变化。
0 评论