Java中的对象构造与初始化顺序
创始人
2024-03-17 16:39:46
0

参考文献:

Java核心技术卷一
Java程序的初始化顺序
Java 代码块和类的执行调用顺序
类的加载与初始化

域初始化

如果在构造器中没有显式地给域赋予初值,那么就会被自动地赋为默认值: 数值为 0、
布尔值为 false、 对象引用为 null。

也可以直接在实例域中设置一个有意义的初值,在执行构造器之前,先执行赋值操作,将所有类对象的该域设置为一样的值。比如:

class Employee
{
private String name ="JXZ";
}

构造器

如果在编写一个类时没有编写构造器, 那么系统就会提供一个无参数构造器。这个构造
器将所有的实例域设置为默认值。

仅当类没有提供任何构造器的时候, 系统才会提供一个默认的构造器。如果类中提供了至少一个构造器, 但是没有提供无参数的构造器, 则在构造对象时如果没有提供参数就会被视为不合法。比如在编写类的时候,已经给出了一个简单的构造器,但是想用new ClassName()构造实例,就必须提供一个默认的构造器(即不带参数的构造器),如果希望所有域被赋予默认值, 可以采用下列格式:

public ClassName(){}

关键字 this 代表引用方法的隐式参数。但其还有一层用法,如果构造器的第一个语句形如 this(...), 这个构造器将调用同一个类的另一个构造器。比如:

public Employee(double s)
{
// 这里就会调用Employee(String, double)
this("Employee #" + nextld, s);
nextld++;
}

初始化块

在一个类的声明中,可以包含多个代码块,只要构造类的对象(实例化),这些块就会被执行,在下面有个例子中可以看到,装载类但没有实例化类的时候,这些普通代码块并没有被执行,与之相对的是静态代码块执行了。

class Employee
{private static int nextld;private int id;private String name;private double salary;// object initialization block{id = nextld;nextld++;}
}

《Java核心技术卷一》中对调用构造器的相关步骤总结如下:

  1. 所有数据域被初始化为默认值(0、false 或 null)
  2. 按照在类声明中出现的次序, 依次执行所有域初始化语句和初始化块
  3. 如果构造器第一行调用了第二个构造器,则执行第二个构造器主体
  4. 执行这个构造器的主体

Java程序的初始化顺序

在加入父子类以及静态代码块后,初始化顺序就复杂一点了,参考Java程序的初始化顺序总结如下:

静态优于非静态,先父后子,域声明优于块,最后构造器

  1. 父类静态变量
  2. 父类静态代码块
  3. 子类静态变量
  4. 子类静态代码块
  5. 父类非静态变量
  6. 父类非静态代码块
  7. 父类构造函数
  8. 子类非静态变量
  9. 子类非静态代码块
  10. 子类构造函数

实例代码:

public class InitOrderDemo {public InitOrderDemo() {System.out.println("父类构造方法");}String b = "父类非静态变量";{System.out.println(b);System.out.println("父类非静态代码块");}static String a = "父类静态变量";static {System.out.println(a);System.out.println("父类静态代码块");}public static void superMethod() {System.out.println("父类普通静态方法");}
}
public class Derived extends InitOrderDemo {public Derived() {System.out.println("子类构造方法");}String b = "子类非静态变量";{System.out.println(b);System.out.println("子类非静态代码块");}static String a = "子类静态变量";static {System.out.println(a);System.out.println("子类静态代码块");}public static void derivedMethod() {System.out.println("子类普通静态方法");}public static void main(String[] args) {
//        InitOrderDemo.superMethod();Derived.derivedMethod();
//        new Derived();}
}

执行输出如下:

InitOrderDemo.superMethod()
父类静态变量
父类静态代码块
子类静态变量
子类静态代码块
父类普通静态方法

Derived.derivedMethod():
父类静态变量
父类静态代码块
子类静态变量
子类静态代码块
子类普通静态方法

new Derived():
父类静态变量
父类静态代码块
子类静态变量
子类静态代码块
父类非静态变量
父类非静态代码块
父类构造方法
子类非静态变量
子类非静态代码块
子类构造方法

其中InitOrderDemo.superMethod() Derived.derivedMethod()的打印只打印出了静态变量和静态代码块,和装载时域的初始化有关。参考类的加载与初始化

同时参考代码块的两个注意事项:

  1. static代码块即静态代码块,随着类的加载而执行,是对类进行初始化,且只会执行一次,当之后再创建对象时,静态代码块不会再执行。普通代码块每创建一次对象便会执行一次。
  2. 普通代码块,在创建对象实例时,会被默认调用,每当创建一次,便会调用一次。如果只是使用类的静态成员时,普通代码块不会被调用执行

相关内容

热门资讯

汽车油箱结构是什么(汽车油箱结... 本篇文章极速百科给大家谈谈汽车油箱结构是什么,以及汽车油箱结构原理图解对应的知识点,希望对各位有所帮...
美国2年期国债收益率上涨15个... 原标题:美国2年期国债收益率上涨15个基点 美国2年期国债收益率上涨15个基...
嵌入式 ADC使用手册完整版 ... 嵌入式 ADC使用手册完整版 (188977万字)💜&#...
重大消息战皇大厅开挂是真的吗... 您好:战皇大厅这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...
盘点十款牵手跑胡子为什么一直... 您好:牵手跑胡子这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游...
senator香烟多少一盒(s... 今天给各位分享senator香烟多少一盒的知识,其中也会对sevebstars香烟进行解释,如果能碰...
终于懂了新荣耀斗牛真的有挂吗... 您好:新荣耀斗牛这款游戏可以开挂,确实是有挂的,需要了解加客服微信8435338】很多玩家在这款游戏...
盘点十款明星麻将到底有没有挂... 您好:明星麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【5848499】很多玩家在这款游戏...
SAP PS 第9节 合并采购... SAP PS 第9节 合并采购申请、组合WBS之影响1 合并采购申请1.1 合并采购申请后台配置1....
总结文章“新道游棋牌有透视挂吗... 您好:新道游棋牌这款游戏可以开挂,确实是有挂的,需要了解加客服微信【7682267】很多玩家在这款游...