ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

浅谈Java类中的变量初始化顺序

2021-08-04 13:33:36  阅读:167  来源: 互联网

标签:初始化 Java 浅谈 int System println public 类中 out


一、变量与构造器的初始化顺序

我们知道一个类中具有类变量、类方法和构造器(方法中的局部变量不讨论,他们是在方法调用时才被初始化),当我们初始化创建一个类对象时,其初始化的顺序为:先初始化类变量,再执行构造器方法。

代码验证:

public class Demo01 {
    public int a1 = 1;
    public String a2 = "initiaied!";

    public Demo01() {
        System.out.println(a1);
        System.out.println(a2);
        System.out.println("构造器方法被执行");
    }

    public static void main(String[] args) {
        Demo01 demo01 = new Demo01();
    }
}

运行结果:
     1
     initiaied!
     构造器方法被执行

可以看出,当我们创建一个Demo01对象时,先初始化了变量a1和a2,然后执行构造器方法。

二、静态变量与非静态变量的初始化顺序

静态变量是属于类本身,无论创建多少个对象,静态变量都只有一份存储区域,因此他会在类首次被访问或者首次创建类对象时被初始化,而且有且只能初始化一次。

而非静态变量是属于每个对象,他是在创建每个对象时都初始化一次。因此,静态变量要先于非静态进行初始化。例子:

public class Demo02 {
    public Cup cup1 = new Cup(1);
    public static Cup cup2 = new Cup(2);

    public Demo02() {
        System.out.println("Demo02构造器被执行!");
    }

    public static void main(String[] args) {
        Demo02 demo02 = new Demo02();
        Demo02 demo02_01 = new Demo02();
    }
}

class Cup {
    public Cup(int i) {
        System.out.println("Cup->" + i);
    }
}


运行结果:
        Cup->2
        Cup->1
        Demo02构造器被执行!
        Cup->1
        Demo02构造器被执行

当程序要执行main方法时,会先加载Demo02类文件,在加载时就会先初始化静态变量cup2,因此控制台输出"cup->2"。

类加载完后,开始执行main方法,创建demo02对象,这时就会初始化类中的非静态变量cup1,控制台输出"cup->1",然后执行构造器方法。创建第二个对象时,只初始化cup1,cup2为静态变量只初始化一次。

三、静态代码块与非静态代码块

静态代码块本质上就是一段静态变量的代码,其初始化和静态变量没有区别:当类首次被访问或者首次创建该类对象时被初始化,并且只初始化一次。

非静态代码块就是一段非静态变量的代码,他和非静态变量的初始化没有区别。

public class Demo03 {
    static Table table1;
    Table table2;

    static {
        table1 = new Table(1);
    }

    {
        table2 = new Table(2);
    }

    public Demo03() {
        System.out.println("Demo03构造器被执行");
    }

    public static void main(String[] args) {
        new Demo03();
    }
}

class Table {
    public Table(int i) {
        System.out.println("Table->" + i);
    }
}

运行结果:
        Table->1
        Table->2
        Demo03构造器被执行

四、父类与子类的初始化顺序

没有父类就没有子类,因此无论是类加载还是创建实例对象,父类都优先于子类进行初始化。

public class Demo04 extends Insect {
    private int k = fun("Demo04中的k被初始化");
    private static int x2 = fun("Demo04中的x2被初始化");

    public Demo04() {
        System.out.println("k=" + k);
        System.out.println("j=" + j);
    }

    public static void main(String[] args) {
        Demo04 demo04 = new Demo04();
    }
}

class Insect {
    public int i = 9;
    public int j;
    public static int x1 = fun("Insect中的x1被初始化");

    public Insect() {
        System.out.println("i=" + i + ",j=" + j);
        j = 39;
    }

    public static int fun(String s) {
        System.out.println(s);
        return 47;
    }
}
运行结果:
        Insect中的x1被初始化
        Demo04中的x2被初始化
        i=9,j=0
        Demo04中的k被初始化
        k=47
        j=39

当执行main方法时,加载器开始加载Demo04类文件,在加载过程中,加载器会注意到他有一个父类Insect还没被加载,因此会先加载父类Insect文件。

类加载过程中会完成静态变量的初始化(此时并不执行构造器方法,构造器方法只有在创建对象时调用),Insect类加载完成后,接着加载Demo04类,都加载完成后,就开始执行main方法中的代码,创建Demo04对象。

由于继承关系,因此先创建父类Insect的实例对象,因此父类中的变量初始化和构造器先被执行,然后在初始化子类Demo04中的非静态变量和执行构造器方法。

五、总结

最后放一段代码,把前面所说情况都放在一起。

public class Son extends Father {
    int m = fun("Son中的m 被初始化");

    public Son() {
        System.out.println("m = " + m);
        System.out.println("j = " + j);
    }

    public static int x3 = fun("Son中的x3 被初始化");

    public static void main(String[] args) {
        Son son = new Son();
    }
}

class Father extends GrandFather {

    public int k = fun("Father中的k被初始化");
    public static int x2 = fun("Father中的x2被初始化");

    public Father() {
        System.out.println("k=" + k);
        System.out.println("j=" + j);
    }
}

class GrandFather {
    public int i = 9;
    public int j;
    public static int x1 = fun("GrandFather中的x1被初始化");

    public GrandFather() {
        System.out.println("i=" + i + ",j=" + j);
        j = 39;
    }

    public static int fun(String s) {
        System.out.println(s);
        return 47;
    }
}
运行结果:
        GrandFather中的x1被初始化
        Father中的x2被初始化
        Son中的x3 被初始化
        i=9,j=0
        Father中的k被初始化
        k=47
        j=39
        Son中的m 被初始化
        m = 47
        j = 39

 

标签:初始化,Java,浅谈,int,System,println,public,类中,out
来源: https://www.cnblogs.com/ecust-cyh/p/15098427.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有