【Java基础知识系列】之Java类的初始化顺序

Scroll Down

前言

类的执行顺序

类的初始化顺序

  • 简单场景
    • 代码示例
    public class Person {
      private String name = initName();
    
      private String initName() {
          System.out.println("【父类】初始化实例变量name");
          return "【父类】史蒂夫";
      }
    
      private int age;
    
      private static int staticVar1 = initStaticVar1();
      private static int staticVar2;
    
      private static int initStaticVar1() {
          System.out.println("【父类】初始化静态变量staticVar1");
          return 100;
      }
    
      public Person() {
          System.out.println("【父类】我是无参构造方法");
      }
    
      public Person(String name, int age) {
          System.out.println("【父类】我是有参构造方法");
          this.name = name;
          this.age = age;
      }
    
      {
          System.out.println("【父类】我是实例代码块");
      }
    
      static {
          System.out.println("【父类】我是静态代码块");
      }
    
    
    }
    
    public class PersonTest {
      @Test
      public void testInitPerson() {
          Person person = new Person();
          System.out.println();
          Person person1 = new Person();
          System.out.println();
          Person person2= new Person("工藤新一",22);
    
      }
    
    }
    
    • 输出结果
    【父类】初始化静态变量staticVar1
    【父类】我是静态代码块
    【父类】初始化实例变量name
    【父类】我是实例代码块
    【父类】我是无参构造方法
    
    【父类】初始化实例变量name
    【父类】我是实例代码块
    【父类】我是无参构造方法
    
    【父类】初始化实例变量name
    【父类】我是实例代码块
    【父类】我是有参构造方法
    
  • 复杂场景(有继承)
    • 代码示例
    public class Man extends Person {
      private String name = initName();
    
      private String initName() {
          System.out.println("【子类】初始化实例变量name");
          return "【子类】工一";
      }
    
      private int age;
    
      private static int staticVar1 = initStaticVar1();
      private static int staticVar2;
    
      private static int initStaticVar1() {
          System.out.println("【子类】初始化静态变量staticVar1");
          return 100;
      }
    
      public Man() {
          System.out.println("【子类】我是无参构造方法");
      }
    
      public Man(String name, int age) {
          System.out.println("【子类】我是有参构造方法");
          this.name = name;
          this.age = age;
      }
    
      {
          System.out.println("【子类】我是实例代码块");
      }
    
      static {
          System.out.println("【子类】我是静态代码块");
      }
    
    
    }
    
    public class ManTest {
      @Test
      public void testInitMan() {
          Man man = new Man();
          System.out.println();
          Man man1 = new Man();
          System.out.println();
          Man man2 = new Man("工藤新一", 22);
    
      }
    
    }
    
    • 输出结果
    【父类】初始化静态变量staticVar1
    【父类】我是静态代码块
    【子类】初始化静态变量staticVar1
    【子类】我是静态代码块
    【父类】初始化实例变量name
    【父类】我是实例代码块
    【父类】我是无参构造方法
    【子类】初始化实例变量name
    【子类】我是实例代码块
    【子类】我是无参构造方法
    
    【父类】初始化实例变量name
    【父类】我是实例代码块
    【父类】我是无参构造方法
    【子类】初始化实例变量name
    【子类】我是实例代码块
    【子类】我是无参构造方法
    
    【父类】初始化实例变量name
    【父类】我是实例代码块
    【父类】我是无参构造方法
    【子类】初始化实例变量name
    【子类】我是实例代码块
    【子类】我是有参构造方法
    

结论

  • 简单场景
    静态变量>静态代码块>实例变量>实例代码块>构造方法

    其中静态代码块和静态变量只会执行一次(第一次new对象的时候会执行)
  • 有继承场景
    【父类】静态变量>【父类】静态代码块>【子类】静态变量>【子类】静态代码块>【父类】实例变量>【父类】实例代码块>【父类】构造方法>【父类】实例变量>【父类】实例代码块>【父类】构造方法

    其中【父类】静态变量 、【父类】静态代码块、【子类】静态变量 、【子类】静态代码块只会执行一次(第一次new对象的时候会执行)

术语

  • 静态变量
  • 成员变量
  • 静态代码块
  • 实例代码块
  • 构造方法

你问我答

1.Q:静态变量,成员变量,静态代码块、动态代码块、构造方法在代码中的位置顺序会影响执行结果么?

A:不会

源码地址

Java类的初始化顺序-源码

参考文章