【一】类初始化和实例初始化

类初始化过程

  • 一个类要创建实例需要先加载并初始化该类
  • main方法所在的类需要先加载和初始化
  • 一个子类初始化前需要先初始化父类
  • 一个类初始化就是执行<clinit>()方法
  • 由静态类变量显示赋值代码 和静态块组成,按代码顺序执行
  • <clinit>()只执行一次

实例初始化过程

  • 实例初始化就是执行<init>()方法
  • <init>()可能重载有多个,有几个构造器就有几个<init>()方法
  • ()方法由非静态实例变量显示赋值代码和构造块、构造方法组成
  • 非静态实例变量显示赋值代码 和构造块 从上到下按顺序执行,构造方法最后执行
  • 每次创建实例对象,调用构造方法,执行的就是<init>()方法
  • <init>()方法的首行就是super()或super(实参),即执行父类的<init>()

执行顺序

  1. 父类静态变量和静态块(按代码顺序执行)
  2. 子类静态变量和静态块(按代码顺序执行)
  3. 父类非静态实例变量显示赋值代码 和构造块(按代码顺序执行)
  4. 父类构造方法最后执行,并初始化父类普通成员变量
  5. 子类非静态实例变量显示赋值代码 和构造块(按代码顺序执行)
  6. 子类构造方法最后执行,并初始化子类普通成员变量

构造块与静态块

  • 静态块:用static申明,JVM加载类时执行,仅执行一次
  • 构造块:类中直接用{}定义,每一次创建对象时执行
public class Test {
    //静态对象
    public static char text = 'a';

    //构造函数
    public Test() {
        System.out.println('c');
    }

    //构造块
    {
        System.out.println('b');
    }

    //静态块
    static {
        System.out.println(text);
    }

    public static void main(String[] args) {
        Test a = new Test();
    }
}

控制台:

a
b
c

执行顺序优先级:静态块>main()>构造块>构造方法

构造块不具有独立执行的能力,编译器会把构造代码块插入到每个构造函数的最前端,构造代码块不是在构造函数之前运行,而是依托于构造函数

然而,这里的静态块,并不是仅仅静态块,而是静态域,包含了静态变量,静态块,这两者的执行顺序就是按照位置顺序进行。

this特殊情况

public class Client {
    public static int count = 0;

    {
        count++;
    }

    public Client() {

    }

    public Client(int i) {
        this();
    }

    public Client(String string) {
    }

    public static void main(String[] args) {
        System.out.println(Client.count);
        
        new Client();
        System.out.println(Client.count);
        
        new Client(1);
        System.out.println(Client.count);
        
        new Client("1");
        System.out.println(Client.count);
    }
}

控制台

0
1
2
3

new Client(1);执行时,先调用构造块,再执行this();,遇到this关键字(也就是构造函数调用自身其他的构造函数时)不插入构造代码块(构造代码块的出现就是为了提取构造函数的共同量,减少各个构造函数的代码而产生的.)

super方法没有任何特殊的地方.编译器只是把构造代码块插入到super方法之后执行而已.

方法的重写

哪些方法不可以被重写

  • final
  • 静态
  • private

对象的多态性

子类重写父类方法,子类对象调用的是子类重写后的方法
非静态方法的默认对象是this,this在构造器(或)表示正在创建的对象

示例

/**
 * 父类的初始化<clinit>:
 * 1、j = method()
 * 2、static {}
 * <p>
 * 父类的实例化方法:
 * 1、super()
 * 2、i = test();
 * 3、构造块
 * 4、构造方法
 * <p>
 * 非静态方法的前面其实有个默认的对象this,this在构造器(或<init>)表示正在创建的对象
 */
public class Father {
    private int i = test();
    private static int j = method();

    static {
        System.out.print("1 ");
    }

    Father() {
        System.out.print("2 ");
    }

    {
        System.out.print("3 ");
    }

    int test() {
        System.out.print("4 ");
        return 1;
    }

    static int method() {
        System.out.print("5 ");
        return 1;
    }
}

/**
 * 先初始化父类           5 1
 * 再初始化子类<clinit>:  10 6
 * 1、j = method()
 * 2、static {}
 * <p>
 * 子类的实例化方法:
 * 1、super()        9 3 2
 * 2、i = test();    9
 * 3、构造块          8
 * 4、构造方法        7
 * <p>
 * 因为创建两个对象,实例初始化执行两次
 */
public class Son extends Father {
    private int i = test();
    private static int j = method();

    static {
        System.out.print("6 ");
    }

    Son() {
//        super(); 写与不写,均会调用父类构造器
        System.out.print("7 ");
    }

    {
        System.out.print("8 ");
    }

    int test() {
        System.out.print("9 ");
        return 1;
    }

    static int method() {
        System.out.print("10 ");
        return 1;
    }

    public static void main(String[] args) {
        Son s1 = new Son();
        System.out.println();
        Son s2 = new Son();
    }
}

console

5 1 10 6 9 3 2 9 8 7 
9 3 2 9 8 7 
发布了38 篇原创文章 · 获赞 0 · 访问量 1156

猜你喜欢

转载自blog.csdn.net/qq_25046005/article/details/103685284