欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Java高频面试题】--类的初始化过程以及实例的初始化过程

程序员文章站 2022-07-14 15:14:55
...

1.1 类的初始化过程

  • 要创建一个类的实例,必须加载和初始化该类。
    • main()方法所在的类,会被优先加载并初始化
  • 子类初始化前,会先加载并初始化它的父类
  • 初始化一个类,其实质上就是执行了<client>()方法
    • <client>()方法包含了,静态变量显式赋值代码以及静态代码块
    • 静态变量显式赋值代码以及静态代码块的执行顺序,由它们的先后顺序执行,先声明的先执行
  • <client>()方法只会执行一次

如以下代码:

//静态变量显式赋值代码
private static int j=method();

//静态代码块
static {
    System.out.println("(1)");
}

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

相应字节码:

// access flags 0x9
  public static method()I
   L0
    LINENUMBER 40 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "(5)"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    LINENUMBER 41 L1
    ICONST_1
    IRETURN
    MAXSTACK = 2
    MAXLOCALS = 0

// access flags 0x8
  static <clinit>()V
   L0
    LINENUMBER 14 L0
    INVOKESTATIC com/qingyun/demo/load/Father.method ()I
    PUTSTATIC com/qingyun/demo/load/Father.j : I
   L1
    LINENUMBER 18 L1
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "(1)"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L2
    LINENUMBER 19 L2
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 0

【Java高频面试题】--类的初始化过程以及实例的初始化过程

1.2 实例的初始化过程

  • 实例化一个类其实质上是执行了<init>()方法。
    • 类中有多少个构造器就会有多少个<init>()方法。
  • <init>()方法由非静态显式赋值代码、非静态代码块组成以及对应的构造器代码组成。
  • <init>()方法的执行顺序是,优先执行非静态显式赋值代码、非静态代码块,它们俩那个在前那个先执行,构造器对应代码最后执行。
  • 每次创建实例,调用构造器,就是调用其对应的<init>()方法。
  • 需要注意的是,在子类中,<init>()方法的第一行是super()方法,即对应的父类的<init>()方法

如下代码:

父类代码:

package com.qingyun.demo.load;

/**
 * Created with IntelliJ IDEA.
 * User: 李敷斌.
 * Date: 2020-05-11
 * Time: 13:49
 * Explain: 父类
 */
public class Father {
    //非静态变量显式赋值代码
    private int i=test();
    //静态变量显式赋值代码
    private static int j=method();

    //静态代码块
    static {
        System.out.println("(1)");
    }

    //构造方法
    Father(){
        System.out.println("(2)");
    }

    //非静态代码块
    {
        System.out.println("(3)");
    }


    public int test(){

        System.out.println("(4)");

        return 1;
    }

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

父类对应字节码:

// class version 52.0 (52)
// access flags 0x21
public class com/qingyun/demo/load/Father {

  // compiled from: Father.java

  // access flags 0x2
  private I i

  // access flags 0xA
  private static I j

  // access flags 0x0
  <init>()V
   L0
    LINENUMBER 22 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
   L1
    LINENUMBER 12 L1
    ALOAD 0
    ALOAD 0
    INVOKEVIRTUAL com/qingyun/demo/load/Father.test ()I
    PUTFIELD com/qingyun/demo/load/Father.i : I
   L2
    LINENUMBER 28 L2
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "(3)"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L3
    LINENUMBER 23 L3
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "(2)"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L4
    LINENUMBER 24 L4
    RETURN
   L5
    LOCALVARIABLE this Lcom/qingyun/demo/load/Father; L0 L5 0
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x1
  public test()I
   L0
    LINENUMBER 34 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "(4)"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    LINENUMBER 36 L1
    ICONST_1
    IRETURN
   L2
    LOCALVARIABLE this Lcom/qingyun/demo/load/Father; L0 L2 0
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x9
  public static method()I
   L0
    LINENUMBER 40 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "(5)"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    LINENUMBER 41 L1
    ICONST_1
    IRETURN
    MAXSTACK = 2
    MAXLOCALS = 0

  // access flags 0x8
  static <clinit>()V
   L0
    LINENUMBER 14 L0
    INVOKESTATIC com/qingyun/demo/load/Father.method ()I
    PUTSTATIC com/qingyun/demo/load/Father.j : I
   L1
    LINENUMBER 18 L1
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "(1)"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L2
    LINENUMBER 19 L2
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 0
}

子类代码:

package com.qingyun.demo.load;

/**
 * Created with IntelliJ IDEA.
 * User: 李敷斌.
 * Date: 2020-05-11
 * Time: 13:49
 * Explain: 子类
 */
public class Son extends Father{
    //非静态变量显式赋值代码
    private int i=test();
    //静态变量显式赋值代码
    private static int j=method();

    //静态代码块
    static {
        System.out.println("(6)");
    }

    //构造方法
    Son(){
        System.out.println("(7)");
    }

    //非静态代码块
    {
        System.out.println("(8)");
    }


    @Override
    public int test(){

        System.out.println("(9)");

        return 1;
    }

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

    public static void main(String[] args) {
        Son son1=new Son();

        System.out.println();

        Son son2=new Son();
    }
}

子类对应字节码:

// class version 52.0 (52)
// access flags 0x21
public class com/qingyun/demo/load/Son extends com/qingyun/demo/load/Father {

  // compiled from: Son.java

  // access flags 0x2
  private I i

  // access flags 0xA
  private static I j

  // access flags 0x0
  <init>()V
   L0
    LINENUMBER 22 L0
    ALOAD 0
    INVOKESPECIAL com/qingyun/demo/load/Father.<init> ()V
   L1
    LINENUMBER 12 L1
    ALOAD 0
    ALOAD 0
    INVOKEVIRTUAL com/qingyun/demo/load/Son.test ()I
    PUTFIELD com/qingyun/demo/load/Son.i : I
   L2
    LINENUMBER 28 L2
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "(8)"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L3
    LINENUMBER 23 L3
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "(7)"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L4
    LINENUMBER 24 L4
    RETURN
   L5
    LOCALVARIABLE this Lcom/qingyun/demo/load/Son; L0 L5 0
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x1
  public test()I
   L0
    LINENUMBER 35 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "(9)"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    LINENUMBER 37 L1
    ICONST_1
    IRETURN
   L2
    LOCALVARIABLE this Lcom/qingyun/demo/load/Son; L0 L2 0
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x9
  public static method()I
   L0
    LINENUMBER 41 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "(10)"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    LINENUMBER 42 L1
    ICONST_1
    IRETURN
    MAXSTACK = 2
    MAXLOCALS = 0

  // access flags 0x9
  public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 46 L0
    NEW com/qingyun/demo/load/Son
    DUP
    INVOKESPECIAL com/qingyun/demo/load/Son.<init> ()V
    ASTORE 1
   L1
    LINENUMBER 48 L1
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    INVOKEVIRTUAL java/io/PrintStream.println ()V
   L2
    LINENUMBER 50 L2
    NEW com/qingyun/demo/load/Son
    DUP
    INVOKESPECIAL com/qingyun/demo/load/Son.<init> ()V
    ASTORE 2
   L3
    LINENUMBER 51 L3
    RETURN
   L4
    LOCALVARIABLE args [Ljava/lang/String; L0 L4 0
    LOCALVARIABLE son1 Lcom/qingyun/demo/load/Son; L1 L4 1
    LOCALVARIABLE son2 Lcom/qingyun/demo/load/Son; L3 L4 2
    MAXSTACK = 2
    MAXLOCALS = 3

  // access flags 0x8
  static <clinit>()V
   L0
    LINENUMBER 14 L0
    INVOKESTATIC com/qingyun/demo/load/Son.method ()I
    PUTSTATIC com/qingyun/demo/load/Son.j : I
   L1
    LINENUMBER 18 L1
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "(6)"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L2
    LINENUMBER 19 L2
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 0
}

这里需要注意的是,以上代码中涉及到了方法的重写:

  • 重写指的是子类重写父类的方法,其方法名与父类对应方法相同
  • 访问修饰符的访问权限不能够更低
  • 被final、static、private关键字修饰的方法不能够被重写。

所以当实例化子类成员是,调用的是子类中重写的test()方法。

对象的多态性:

  • 子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码
  • 非静态方法默认的调用对象是this
  • this对象在构造器或者说<init>方法中就是正在创建的对象

实例的初始化顺序流程图(省略类的加载以及初始化过程):
【Java高频面试题】--类的初始化过程以及实例的初始化过程

相关标签: Java高频面试题