Java对象初始化的过程示例

时间:2022-06-03 19:40:54

单一对象的初始化过程

△概念

所谓对象的初始化过程,就是当你new了一个对象之后,对象所在类的各个成分执行顺序。

△类的成分,各个成分的作用

→成员变量:分为静态成员变量以及普通成员变量。

→成员方法:如果仅仅只是new了一个对象,不会调用成员方法,除非构造方法里面调用成员方法,这个不在这里论述。

→代码块:分为静态代码块以及构造代码块。静态代码块是用来初始化类,当在程序里面首次使用一个类时,会执行他,第二次再使用一个类时,不执行他。构造代码块用来初始化对象,而且是初始化所有对象,每次创建对象都会执行

→构造方法:用来对对象做初始化,可能会有多个不同重载方法。


△示例程序

/**
演示对象的初始化过程
*/
public class My
{

public static void main(String[] args)
{
System.out.println("Hello World!");
Person p1 = new Person();
// Person p2 = new Person(4);
}
}

class Person
{
private String name = "haha";
private int age = 4;
private static String country = "China";
static{
System.out.println("静态代码块初始化"+"conutry=="+country);
}
{
System.out.println("构造代码块初始化--"+"name=="+name+"--age=="+age);
}
Person(){
System.out.println("无参构造器初始化");
}
Person(int a){
System.out.println("有参构造其初始化");
}
}


命令行的打印结果:

Java对象初始化的过程示例

 

由此可得,当程序执行new Person();对象初始化的过程如下:

1,静态成员变量的初始化。

2,静态代码块的执行。

3,成员变量的初始化(你看到我打印出了”haha”和”4”,说明成员变量已经初始化了,如果没有做初始化,应该打印null和0).

4,构造代码块的执行。

5,指定构造器初始化。

 

△对象初始化的规律

1:先对类做了初始化,才对对象做初始化。所以静态成员变量比非静态优先做初始化,静态代码块优先于构造代码块的执行。

2:先统一做初始化,在具体到每个对象作初始化。什么意思呢?构造代码块是对所有的对象做初始化用的,构造方法是由类的使用者所特指,所以,构造代码块优先于构造函数执行。就是先统一在具体。

注:为什么成员变量优先于构造代码块初始化,因为构造代码块是对所有的对象做初始化,要对对象做初始化对象就要现有属性,所以,先要加载对象属性,才能执行构造代码块,所以成员变量优先,同样道理,静态成员变量也优先于静态的代码块。

 

△单一对象的初始化过程总结

根据上述演示过程以及规律,总结对象的初始化过程:

→加载类(先有类才能够创建对象),不过加载类这么个行为我们可是看不到的。

→静态成员变量的出始化。

→静态代码块的执行(为了对类做初始化)。

→堆内存里开辟空间(对象放在堆内存里)

→非静态成员变量初始化。

→构造代码块对对象做初始化(所有对象都要执行构造代码块的内容)。

→执行指定的构造方法。

构造方法执行完成之后,对象正式创建完毕。这里你也可以看出,各个对象前面几步是一样的,只有构造方法的执行是不一样的。


继承体系下的对象的初始化过程

△概述

简而言之就是加多了一个类,有了上面那些讲述,继承体系下的对象的初始化相对来讲也并不难,还是先看示例再来分析原因。

△示例代码

import java.io.*;
public class My
{
public static void main(String[] args) throws Exception{
Person p = new Work();
}
}

class Person
{
String name = "lao wang";
int age = 40;
static{
System.out.println("Person static");
}
{
System.out.println("Person 构造代码块的执行");
}


public Person(){
System.out.println("执行Person无参的构造器");
System.out.println("Person.name = "+this.name+"--"+"Person.age = "+this.age);
}
}

class Work extends Person
{
int salary = 4000;
static{
System.out.println("Work static");
}
{
System.out.println("Work 构造代码块的执行");
}
public Work(){
System.out.println("执行Work无参的构造器");
}
}


运行结果:

Java对象初始化的过程示例

 

为什么是上述的结果呢:

继承体系下对象的初始化是这么一个过程:

1,首先,仍然是要先加载类,也就是要对类做初始化,很自然的,先要加载的是超类,然后才要加载子类。

2,当两个类加载完了,就要开始创建对象,先要创建超类对象,然后创建子类对象。

所以我们看到这个打印结果:

超类静态代码块的执行→子类静态代码块的执行(到这一步两个类的类都加载完毕)→超类构造代码块的执行→超类构造方法执行(超类对象创建完毕)→子类构造代码块的执行→子类构造器的执行(到此子类创建完毕)


△继承体系下对象的创建过程小结

结合开头所讲到的一个类的初始化的过程,总结继承体系下的对象创建过程:

→加载超类:初始化超类的静态成员变量,执行超类的静态代码块。

→加载子类:初始化子类的静态成员变量,执行子类的静态代码块。

→创建超类的对象:初始化超类成员变量,执行超类构造代码块及构造函数。

→创建子类的对象:初始化子类成员变量,执行子类构造代码块和构造函数。

毫无疑问超类静态成员的初始化是最先的,这里需要注意的一点是,先初始化子类静态成员变量,才会加载超类对象,并 不是将超类对象初始化完,才会开始加载子类。其实这个也很自然,因为“子类构造方法里面,默认会去调用超类无参构造方法”所以当然先要加载子类,才会开始创建超类对象。