Java 中的非法訪問錯誤
- java
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
,我們需要查看類定義的變化。