zoukankan      html  css  js  c++  java
  • Java程序员的日常 —— Java类加载中的顺序

    之前说过Java中类的加载顺序,这次看完继承部分,就结合继承再来说说类的加载顺序。

    继承的加载顺序

    由于static块会在首次加载类的时候执行,因此下面的例子就是用static块来测试类的加载顺序。

    package xing.test.thinking.chap7;
    class A{
    	static{
    		System.out.println("A static");
    	}
    }
    class B extends A{
    	static{
    		System.out.println("B static");
    	}
    }
    class C extends B{
    	private static D d = new D();
    	static{
    		System.out.println("C static");
    	}
    }
    class D{
    	static{
    		System.out.println("D static");
    	}
    }
    public class ExtendTest {
    	public static void main(String[] args) {
    		C c = new C();
    	}
    }
    

    在上面的例子中,类C继承B,B继承A,而C有依赖于D。因此当创建C的时候,会自动加载C继承的B和依赖的D,然后B又会加载继承的A。只有A加载完,才能顺利的加载B;BD加载完,才能加载C。这就是类的加载顺序了。

    A static
    B static
    D static
    C static
    

    所有的变量初始化完,才会执行构造方法

    在类的加载过程中,只有内部的变量创建完,才会去执行这个类的构造方法。

    package xing.test.thinking.chap7;
    class A2{
    	B2 b2 = new B2();
    	static{
    		System.out.println("A static");
    	}
    	public A2() {
    		System.out.println("A2()");
    	}
    }
    class B2{
    	C2 c2 = new C2();
    	D2 d2 = new D2();
    	static{
    		System.out.println("B static");
    	}
    	public B2() {
    		System.out.println("B2()");
    	}
    }
    class C2{
    	static{
    		System.out.println("C static");
    	}
    	public C2() {
    		System.out.println("C2()");
    	}
    }
    class D2{
    	static{
    		System.out.println("D static");
    	}
    	public D2() {
    		System.out.println("D2()");
    	}
    }
    public class VarTest {
    	public static void main(String[] args) {
    		A2 a2 = new A2();
    	}
    }
    

    在上面的例子中,A2里面有B2变量,B2则有C2D2变量。因此类的加载还是先读取到哪个,就执行相应的静态块。
    当依赖的对象都定义完,才会执行构造方法:

    A static
    B static
    C static
    C2()
    D static
    D2()
    B2()
    A2()
    

    静态成员与普通成员类的加载区别

    在类的加载过程中,静态成员类的对象,会优先加载;而普通成员类的对象则是使用的时候才回去加载。

    package xing.test.thinking.chap7;
    class A3{
    	B3 b3 = new B3();
    	static C3 c4 = new C3();
    	static{
    		System.out.println("A3");
    	}
    }
    class B3{
    	static{
    		System.out.println("B3");
    	}
    }
    class C3{
    	static{
    		System.out.println("C3");
    	}
    }
    public class StaticTest {
    	public static void main(String[] args) {
    		A3 a3 = new A3();
    	}
    }
    

    输出:

    C3
    A3
    B3
    

    总结

    第一点,所有的类都会优先加载基类
    第二点,静态成员的初始化优先
    第三点,成员初始化后,才会执行构造方法
    第四点,静态成员的初始化与静态块的执行,发生在类加载的时候。
    第四点,类对象的创建以及静态块的访问,都会触发类的加载。

    补充类构造方法的顺序

    看代码:

    package xing.test.thinking.chap8;
    class A{
    	public A() {
    		System.out.println("A");
    	}
    }
    class B extends A{
    	public B() {
    		System.out.println("B");
    	}
    }
    class C extends B {
    	private D d1 = new D("d1");
    	private D d2 = new D("d2");
    	public C() {
    		System.out.println("C");
    	}
    }
    class D {
    	public D(String str) {
    		System.out.println("D "+str);
    	}
    }
    public class ExtendTest {
    	public static void main(String[] args) {
    		C c = new C();
    	}
    }
    
    

    执行结果:

    A
    B
    D d1
    D d2
    C
    
    

    因此可以得出结论:

    • 首先会调用基类的构造方法
    • 其次,调用成员的构造方法
    • 最后,调用自己的构造方法
  • 相关阅读:
    JS实现简单的运行代码 & 侧边广告
    JS封装Cookie
    [PHP]array_map与array_column之间的关系
    [PHP]json_encode增加options参数后支持中文
    [CI]CodeIgniter特性 & 结构
    [PHP]PHP缓存机制之Output Control
    [PHP]将回调函数作用到给定数组的单元上
    [Apache]网站页面静态化与Apache调优(图)
    [PHP]PHP自定义遍历目录下所有文件的方法
    [PC]PHPCMS配置文件的读取
  • 原文地址:https://www.cnblogs.com/xing901022/p/5507086.html
Copyright © 2011-2022 走看看