java类加载 静态变量和构造方法加载顺序

2 篇文章 0 订阅
  • demo1

/**
 * java规定,变量没有初始化不能使用,全局变量也就是类的属性,java会在编译的时候,自动将他们初始化,
 * 所以可以不进行变量初始化的操作,☆☆☆☆☆但是(局部)变量必须初始化☆☆☆☆☆
 *
 * 静态数据的初始化
 * 初始化的顺序是:先静态对象,而后是“非静态”对象。
 *
 * 非静态成员初始化
 * 在一个类中,非静态成员的初始化,发生在任何方法(包括构造方法)被调用之前。并且它们定义的顺序,决定了初始化的顺序
 * 变量初始化完成之后才厚调用构造函数
 *
 * 先加载类:执行静态块,静态变量赋值 因为静态部分是依赖于类,而不是依赖于对象存在的,所以静态部分的加载优先于对象存在
 *
 *
 */
public class Singleton {

    //1.
    private static int x = 0;

    private static int y;

    //2.
    private static Singleton instance = new Singleton();

    /**
     * -----------------------------------------------------------------------------------------
     * 构造方法是new对象的时候进行调用(此时变量已经初始化完成)
     * 如果注释1在上面 注释2在下面 打印结果为 1 1  准备阶段先对静态变量进行x,y进行赋初始值0,0
     * 然后new Singleton对象开始调用构造函数的x++,y++所以x,y的值变为1,1
     *
     * 注意:不可以在构造函数的参数初始化表中对静态成员变量初始化,但是可以在构造函数中修改静态变量的值
     * 如果注释2在上面 注释1在下面 打印结果为 0 1
     * 先进行++操作 x,y的值变为1,1 后面对x,y进行初始化操作
     *
     */
    private Singleton(){
        x++;
        y++;
    }

    public static void main(String[] args) {
        System.out.println(Singleton.x);
        System.out.println(Singleton.y);
    }

}
  • demo2

 class ConstroctTest {
    //静态变量sta1    未赋予初始值
    public static int sta1;
    //静态变量sta1    赋予初始值20
    public static int sta2 = 20;
    private static ConstroctTest test = new ConstroctTest();
    //构造方法中对于静态变量赋值
    private ConstroctTest() {
        System.out.println("123456");
        sta1 ++ ;
        sta2 ++ ;
    }

     /**
      * 打印结果
      * 123456
      * 1
      * 21
      * 1
      * 1
      *
      * 1. 从结果可以看出,Java的静态变量,只是在类第一次加载,初始化的时候执行。
      * 2. 类变量不依赖类的实例,类变量只在初始化时候在栈内存中被分配一次空间,无论类的实例被创建几次,都不再为类变量分配空间。
      * 3. 可以看出 ,类变量的执行与初始化,与实例对象没有关系。
      * @param args
      */
    public static void main(String[] args) {
        System.out.println(ConstroctTest.sta1);
        System.out.println(ConstroctTest.sta2);
        System.out.println(ConstroctTest.sta1);
        System.out.println(ConstroctTest.sta1);
    }
}

  • demo3

class Parent{
    static String name1 = "hello";
    static{
        System.out.println("Parent static block");
    }
    public Parent(){
        System.out.println("Parent construct block");
    }
}
class Child extends Parent{
    static String name2 = "hello";
    static{
        System.out.println("Child static block");
    }
    public Child(){
        System.out.println("Child construct block");
    }
}

 class Test{
     /**
      * 打印结果
      * Parent static block
      * Child static block
      * Parent construct block
      * Child construct block
      *
      * 结果分析:
      * 1. 先初始化父类的静态属性在执行子类的静态属性,再是父类的构造方法再是子类的构造方法。
      * 2. 实例化 Child 类。第一要初始化类Child ,因为Child拥有父类(会判断父类是否初始化),
      * 类的初始化只有一次。初始化类(就是按照顺序加载静态变量与静态方法)。
      * 3. 初始化Child后。开始实例化Child ,因为拥有父类,所以调用构造方法之前会调用父类的默认构造方法。
      *
      * @param args
      */
    public static void main(String[] args){
        Child ch = new Child();
    }
}

  • demo4


 class Animal {
    private static int k;
    static{
        System.out.println("父类的静态方法");
    }
    {
        System.out.println("执行父类的构造代码块");
    }
    public Animal(){
        System.out.println("执行父类的构造方法");
    }

     /**
      * 执行结果  不会打印构造代码块和构造方法中的代码
      * 父类的静态方法
      * 0
      *
      * @param args
      */
    public static void main(String[] args) {
        System.out.println(Animal.k);
    }
}

  • demo5


 class Animal1 {
    private static int k;
    {
        System.out.println("执行父类的构造代码块");
    }
    static{
        System.out.println("父类的静态方法");
    }
    public Animal1(){
        System.out.println("执行父类的构造方法");
    }

     /**
      *
      * 构造代码块先于构造方法执行  静态代码块只会执行一次
      *
      * 执行结果:
      * 父类的静态方法
      * 执行父类的构造代码块
      * 执行父类的构造方法
      * 执行父类的构造代码块
      * 执行父类的构造方法
      * @param args
      */
    public static void main(String[] args) {
        Animal1 animal1 = new Animal1();
        Animal1 animal2 = new Animal1();
    }
}


  • demo6

 class Cat {
     private static int a;
     private static int b = 1000;
     static{
        a = 100;
        b = 200;
    }
    public  Cat cat = new Cat();

    public Cat(){
        a=100000;
        b=200000;
    }


    /**
     *
     * 静态代码块中的内容,看做是赋值操作
     * 如果public  Cat cat = new Cat();不带static 那么输出结果100,200
     * 如果public static Cat cat = new Cat(); 那么输出结果100000,200000
     *
     * 执行结果
     * 100000
     * 200000
     *
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(Cat.a);
        System.out.println(Cat.b);
    }
}


  • demo7

class A {
    static {
        System.out.println("A的静态块");
    }
    private static String staticStr = getStaticStr();
    private String str = getStr();
    {
        System.out.println("A的实例块");
    }
    public A() {
        System.out.println("A的构造方法");
    }
    private static String getStaticStr() {
        System.out.println("A的静态属性初始化");
        return null;
    }
    private String getStr() {
        System.out.println("A的实例属性初始化");
        return null;
    }

    /**
     * A的静态块
     * A的静态属性初始化
     * B的静态属性初始化
     * B的静态块
     * A的实例属性初始化
     * A的实例块
     * A的构造方法
     * B的实例块
     * B的实例属性初始化
     * B的构造方法
     * A的实例属性初始化
     * A的实例块
     * A的构造方法
     * B的实例块
     * B的实例属性初始化
     * B的构造方法
     *
     *
     *由此可见,实例化子类的时候,若此类未被加载过,首先加载是父类的类对象,
     * 然后加载子类的类对象,接着实例化父类,最后实例化子类,若此类被加载过,不再加载父类和子类的类对象。
     *
     * 接下来是加载顺序,当加载类对象时,首先初始化静态属性,然后执行静态块;当实例化对象时,
     * 首先执行构造块(直接写在类中的代码块),然后执行构造方法。
     * 至于各静态块和静态属性初始化哪个些执行,是按代码的先后顺序。属性、构造块(也就是上面的实例块)、
     * 构造方法之间的执行顺序(但构造块一定会在构造方法前执行),也是按代码的先后顺序。
     * @param args
     */
    public static void main(String[] args) {
        new B();
        new B();
    }

}
class B extends A{
    private static String staticStr = getStaticStr();
    static {
        System.out.println("B的静态块");
    }
    {
        System.out.println("B的实例块");
    }
    public B() {
        System.out.println("B的构造方法");
    }
    private String str = getStr();
    private static String getStaticStr() {
        System.out.println("B的静态属性初始化");
        return null;
    }
    private String getStr() {
        System.out.println("B的实例属性初始化");
        return null;
    }
}


  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值