即判斷是否執行<clinit>方法,
被動使用有可能會加載類(JVM規范里沒有說明),根據不同虛擬機實作,如果在加載的程序中,遇到了.class檔案的缺失或者存在錯誤,類加載器只會在首次主動使用它們時才會報錯,如果一直沒有主動使用,則不會報錯
主動
一,使用new關鍵字或者通過反射、克隆、反序列化
二,呼叫類的靜態方法,
三,當使用類、介面的靜態欄位時(final修飾特殊考慮),
四,當使用java.lang.reflect包中的方法反射類的方法時,
五,當初始化子類時,如果發現其父類還沒有進行過初始化,則需要先觸發父類的初始化
interface Parent {
Thread thread = new Thread(){ //匿名內部類
{
System.out.println("Thread...Parent");
}
};
}
class Child implements Parent {
public static int b = 5;
}
public class Test04 {
public static void main(String[] args) {
System.out.println(Child.b);
}
}
//介面繼承或者實作介面類,只有當程式首次使用特定介面的靜態欄位時,才會導致該介面的初始化,而且是參考型別的
//例子中初始化Chlid但并沒有初始化父介面,
六,如果一個介面定義了default方法,那么直接實作或者間接實作該介面的類的初始化,該介面要在其之前被初始化,
interface Parent {
Thread thread = new Thread(){ //匿名內部類
{
System.out.println("Thread...Parent");
}
};
default void a(){
System.out.println("dafsdaf");
}
}
class Child implements Parent {
}
public class Test04 {
public static void main(String[] args) {
Child child=new Child();
}
}
七,jvm啟動時被標明為啟動類的類(如Java Test、main方法所在的類)
八,動態語言,當初次呼叫 MethodHandle 實體時,初始化該 MethodHandle 指向的方法所在類,
被動
一,static final的常量
class F{
static final int count = 1;
static{
System.out.println("Initialize class F");
}
}
public class Test6 {
public static void main(String[] args) {
int x = F.count;
}
}
//static final的常量,F的class檔案刪掉,也不影響程式的正常執行,其在編譯階段就會存入呼叫類的常量池中
class F{
static final String s = UUID.randomUUID().toString();
static{
System.out.println("Initialize class F");
}
}
public class Test6 {
public static void main(String[] args) {
String x = F.s;
}
}
//運行期確定不是常量
二,當通過子類參考父類的靜態變數,不會導致子類初始化
class Dfather{
static int count = 1;
static{
System.out.println("Initialize class Dfather");
}
}
class Dson extends Dfather{
static{
System.out.println("Initialize class Dson");
}
}
public class Test4 {
public static void main(String[] args) {
int x = Dson.count;
}
}
//會加載Dson,但不會初始化,不同虛擬機不同,可通過引數 -verbose:class查看
class C{
static int a=1;
static {
System.out.println("wdfghjkldfgh");
}
}
public class P extends C{
static {
System.out.println("fdsfsf");
}
public static void main(String[] args) {
System.out.println(P.a);
}
}
//注意若運行類直接繼承則會初始化子類
三,通過陣列定義類參考,不會觸發此類的初始化
class E{
static{
System.out.println("Initialize class E");
}
}
public class Test5 {
public static void main(String[] args) {
E[] e = new E[10];
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/430991.html
標籤:Java
