心得经验总结:浅谈Java类中的变量初始化顺序

简介: 心得经验总结:浅谈Java类中的变量初始化顺序

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

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

代码验证:

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();

}//代码效果参考:http://www.ezhiqi.com/bx/art_6913.html

}

运行结果:

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);

}//代码效果参考:http://www.ezhiqi.com/zx/art_5018.html

public Demo03() {

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

}

public static void main(String【】 args) {

new Demo03();

}

}//代码效果参考:http://www.ezhiqi.com/bx/art_701.html

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

相关文章
|
3天前
|
存储 Java
java基础(7)变量以及变量的分类
Java变量是内存中存储数据的基本单元,包含数据类型、名称和字面值。变量的数据类型决定了分配的内存空间大小。变量声明格式为“数据类型 变量名;”,变量名应符合标识符命名规范。变量可以重新赋值,但数据类型需一致。变量可以一行声明多个,作用域决定了变量的可用范围。变量分为局部变量和成员变量,局部变量定义在方法体内,成员变量定义在方法体外、类体内。
18 2
|
3天前
|
Java Linux
java基础(3)安装好JDK后使用javac.exe编译java文件、java.exe运行编译好的类
本文介绍了如何在安装JDK后使用`javac.exe`编译Java文件,以及使用`java.exe`运行编译好的类文件。涵盖了JDK的安装、环境变量配置、编写Java程序、使用命令行编译和运行程序的步骤,并提供了解决中文乱码的方法。
17 1
|
3天前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
12 0
java基础(13)String类
|
14天前
|
Java 编译器
Java——类与对象(继承和多态)
本文介绍了面向对象编程中的继承概念,包括如何避免重复代码、构造方法的调用规则、成员变量的访问以及权限修饰符的使用。文中详细解释了继承与组合的区别,并探讨了多态的概念,包括向上转型、向下转型和方法的重写。此外,还讨论了静态绑定和动态绑定的区别,以及多态带来的优势和弊端。
21 9
Java——类与对象(继承和多态)
|
14天前
|
SQL Java 编译器
Java——类与对象(封装)
封装是面向对象编程中的概念,指将数据(属性)和相关操作(方法)组合成独立单元(类),使外部无法直接访问对象的内部状态,只能通过提供的方法进行交互,从而保护数据安全。例如,手机将各种组件封装起来,只暴露必要的接口供外部使用。实现封装时,使用`private`关键字修饰成员变量,并提供`get`和`set`方法进行访问和修改。此外,介绍了包的概念、导入包的方式及其注意事项,以及`static`关键字的使用,包括静态变量和方法的初始化与代码块的加载顺序。
21 10
Java——类与对象(封装)
|
14天前
|
Java C语言
Java——类与对象
这段内容介绍了Java中的类和对象、`this`关键字及构造方法的基本概念。类是对现实世界事物的抽象描述,包含属性和方法;对象是类的实例,通过`new`关键字创建。`this`关键字用于区分成员变量和局部变量,构造方法用于初始化对象。此外,还介绍了标准JavaBean的要求和生成方法。
20 9
Java——类与对象
|
13天前
|
存储 安全 Java
Java——String类详解
String 是 Java 中的一个类,用于表示字符串,属于引用数据类型。字符串可以通过多种方式定义,如直接赋值、创建对象、传入 char 或 byte 类型数组。直接赋值会将字符串存储在串池中,复用相同的字符串以节省内存。String 类提供了丰富的方法,如比较(equals() 和 compareTo())、查找(charAt() 和 indexOf())、转换(valueOf() 和 format())、拆分(split())和截取(substring())。此外,还介绍了 StringBuilder 和 StringJoiner 类,前者用于高效拼接字符串,后者用于按指定格式拼接字符串
13 1
Java——String类详解
|
4天前
|
存储 Java
Java编程中的对象和类
【8月更文挑战第55天】在Java的世界中,“对象”与“类”是构建一切的基础。就像乐高积木一样,类定义了形状和结构,而对象则是根据这些设计拼装出来的具体作品。本篇文章将通过一个简单的例子,展示如何从零开始创建一个类,并利用它来制作我们的第一个Java对象。准备好让你的编程之旅起飞了吗?让我们一起来探索这个神奇的过程!
24 10
|
1天前
|
安全 Java 编译器
java访问类字段
java访问类字段
|
3天前
|
Java
java的class类
java的class类
18 5