0
点赞
收藏
分享

微信扫一扫

Java类初始化、实例化流程你真的清楚吗


一、前言

最近在SpringAOP的源码,里面涉及到一些类初始化、实例化的顺序,比如AbstractAutoProxyCreator的触发在初始化 bean 之后,实例化 bean之前。特写此文记录一下。

二、流程

1、类初始化流程

  1. 想创建一个类的实例,就需要先加载并初始化该类;
  2. 想要初始化一个子类,就需要先初始化父类(extends);
  3. 所谓类的初始化就是执行​​<clinit>()​​方法:
  • ​<clinit>()​​方法由静态类变量显式的赋值代码 和 静态代码块组成(static关键字);
  • 并且​​<clinit>()​​方法只会执行一次。

2、类实例化流程

实例化一个类时,就是执行​​<init>()​​方法:

  1. ​<init>()​​​方法可能会重载多个,因为有几个构造器就有几个​​<init>()​​方法;
  2. ​<init>()​​方法由非静态实例变量显示赋值代码、非静态代码块、对应构造器代码组成;
  3. 非静态实例变量显示赋值代码、非静态代码块代码从上到下顺序执行(谁先出现谁先加载),构造器的代码最后执行。
  4. 每次创建实例对象时,都会调用相应的构造器,即执行对应的​​<init>()​​方法;
  5. ​<init>()​​​方法的首行是super()或super(Object …),即对应父类的​​<init>()​​方法,也就是说类实例化也是先实例化父类。

3、方法重写过程

1> 方法重写正是对象多态性的体现:

  1. 子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码;
  2. 非静态方法默认的调用对象是this,即:非静态方法前面有一个默认的对象this;
  3. this对象在构造器(​​<init>()​​方法)中其实就是正在创建的对象;

2> 不可被重写的方法?

  • final方法
  • 静态方法
  • private等子类不可见的方法

三、验证

1、代码案例

创建一个父类Father、一个子类Son(extends Father);

1)Father

package com.saint.base.base;

/**
* @author Saint
*/
public class Father {

// 构造器
Father() {
System.out.println("father constructor(1)");
}

// 静态代码块
static {
System.out.println("father static code block(2)");
}

// 普通代码块
{
System.out.println("father common code block(3)");
}

// 静态成员变量
private static int i = staticMember();

// 成员变量
private int j = member();

/**
* 静态方法
*/
public static int staticMember() {
System.out.println("father static method for static member(4)");
return 1;
}

/**
* 成员方法
*/
public int member() {
System.out.println("father method for common member(5)");
return 1;
}
}

2)Son

package com.saint.base.base;

/**
* @author Saint
*/
public class Son extends Father{

// 构造器
Son() {
// super()写或不写,在子类构造器中一定会先调用父类的构造器
// super();
System.out.println("son constructor(6)");
}

// 静态代码块
static {
System.out.println("son static code block(7)");
}

// 普通代码块
{
System.out.println("son common code block(8)");
}

// 静态成员变量
private static int i = staticMember();

// 成员变量
private int j = member();

/**
* 静态方法
*/
public static int staticMember() {
System.out. println("son static method for static member(9)");
return 1;
}

/**
* 成员方法
*/
public int member() {
System.out.println("son method for common member(10)");
return 1;
}

public static void main(String[] args) {
System.out.println("---------第1次实例化Son对象----------");
Son son1 = new Son();
System.out.println();
System.out.println("---------第二次实例化Son对象----------");
Son son2 = new Son();
}
}

2、Son类main()运行结果

Java类初始化、实例化流程你真的清楚吗_子类

1)结果分析

  1. 实例化子类时要先实例化父类;
  2. 先加载父类静态变量和静态代码块,再加载子类静态变量和静态代码块;
  3. 若子类重写父类方法,则父类调用的是子类方法代码;
  4. 然后再先加载父类非静态变量和非静态代码块、构造方法,再加载子类非静态变量和非静态代码块、构造方法;
  5. 仅初始化是静态变量和静态方法会被执行一次;非静态变量、非静态方法、构造器则是对象实例化一次执行一次。


举报

相关推荐

0 条评论