接口初始化规则
接口初始化规则 当java虚拟机初始化一个类时,要求它的所有父类都已经初始化,但是这条规则不适用于接口
在初始化一个类时,并不会先初始化它所实现的接口
在初始化一个接口时,并不会先初始化它的父接口
因此,一个父接口并不会因为它的子接口或者实现类的初始化而初始化,只有当程序首次使用特定接口的静态变量时,才会导致该接口的初始化
样例1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Main { public static void main (String[] args) { new C(); new C(); } } class C { { System.out.println("CC" ); } public C () { System.out.println("c()" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Main { public static void main (String[] args) { new C(); new C(); } } class C { static { System.out.println("CC" ); } public C () { System.out.println("c()" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Main { public static void main (String[] args) { System.out.println(Mychild5.b); } } interface MyParent5 { public static Thread thread = new Thread(){ { System.out.println("MyParent5 invoked" ); } }; } interface Mychild5 extends MyParent5 { int b = 5 ; }
程序输出5,并没有MyParent5 invoked
样例2 把接口改成类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Main { public static void main (String[] args) { System.out.println(Mychild5.b); } } class MyParent5 { public static Thread thread = new Thread(){ { System.out.println("MyParent5 invoked" ); } }; } class Mychild5 extends MyParent5 { public static int b = 5 ; }
则两个都会输出
如果变b变为final的话
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Main { public static void main (String[] args) { System.out.println(Mychild5.b); } } class MyParent5 { public static Thread thread = new Thread(){ { System.out.println("MyParent5 invoked" ); } }; } class Mychild5 extends MyParent5 { public static final int b = 5 ; }
正好验证了之前学的结论,b已经被放到常量池中,这时候与Mychild5
和MyParent5
都没有关系,即使删掉这两者.class
文件都可以运行
样例3 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Main { public static void main (String[] args) { System.out.println(Mychild5.b); } } interface MyGrandpa { public static Thread thread = new Thread(){ { System.out.println("MyGrandpa invoked" ); } }; class MyParent5 extends MyGrandpa { public static Thread thread = new Thread(){ { System.out.println("MyParent5 invoked" ); } }; } class Mychild5 extends MyParent5 { public static final int b = 5 ; }
只输出5
因为输出b并不会导致MyParent5的初始化,更不会导致接口的初始化。
改成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Main { public static void main (String[] args) { System.out.println(Mychild5.b); } } class MyGrandpa { public static Thread thread = new Thread(){ { System.out.println("MyGrandpa invoked" ); } }; } class MyParent5 extends MyGrandpa { public static Thread thread = new Thread(){ { System.out.println("MyParent5 invoked" ); } }; } class Mychild5 extends MyParent5 { public static int b = 5 ; }
则三者都会输出
其加载顺序
1 2 3 [Loaded MyGrandpa from file:/home/cc/IdeaProjects/test/out/production/test/] [Loaded MyParent5 from file:/home/cc/IdeaProjects/test/out/production/test/] [Loaded Mychild5 from file:/home/cc/IdeaProjects/test/out/production/test/]