• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Y-wee
博客园    首页    新随笔    联系   管理     

Java类初始化和实例初始化

Java类初始化和实例初始化

类初始化过程

一个类初始化就是执行<clint>()方法,该方法由静态变量显式赋值代码和静态代码块组成

静态变量显式赋值代码和静态代码块从上到下顺序执行

<clint>()方法只执行一次

子类初始化需要先初始化父类

实例初始化过程

实例初始化就是执行<init>()方法,该方法可能重载多个,有几个构造器就有几个<init>()方法

<init>()方法由非静态实例变量显式赋值代码和非静态代码块、对应构造器代码组成

非静态实例变量显式赋值代码和非静态代码块从上到下顺序执行,对应构造器代码最后执行

<init>()方法的首行是super()或super(实参列表),即对应父类的<init>()方法,所以执行子类的<init>()方法之前会先执行父类的<init>()方法,讲直白一些:在子类构造器中一定会调用父类的构造器

super()写或不写都会存在构造器首行,实例初始化需要先加载并初始化该类

代码实战

父类

package com.yl;

/**
 * 父类
 *
 * @author Y-wee
 */
public class Father {
    private int i=getI();
    private static int j=getJ();

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

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

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

    public int getI() {
        System.out.print("-4-");
        return 1;
    }

    public static int getJ(){
        System.out.print("-5-");
        return 1;
    }

}

子类

package com.yl;

/**
 * 子类
 *
 * @author Y-wee
 */
public class Son extends Father {
    private int i = getI();
    private static int j = getJ();

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

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

    public Son() {
        System.out.print("-7-");
    }

    @Override
    public int getI() {
        System.out.print("-9-");
        return 1;
    }

    public static int getJ() {
        System.out.print("-10-");
        return 1;
    }

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

输出结果:

解析:

  • sonA实例初始化之前会加载并初始化Son类

  • 由于Son类继承了Father类,所以会先加载并初始化Father类

  • 由类初始化过程可知先输出:5、1

  • Father类初始化之后再初始化Son类,输出:10、6

  • 子类和父类都初始化完成,开始实例初始化

  • 子类实例初始化之前会先执行父类实例初始化

  • 由实例初始化过程可知,先执行Father类的非静态实例变量显式赋值代码:

    private int i=getI();
    

非静态方法前面其实有一个默认的对象this,this在构造器或<init>()方法中表示的是正在创建的对象,因为这里是在创建Son对象,所以执行的是子类的getI()方法

这里可能有人会有疑问,子类同样重写了父类的getJ()方法,为什么父类初始化时执行的不是子类的getJ()方法,因为:final方法、静态方法、private等子类中不可见方法是不能被重写的,所以子类并没有重写父类的getJ()方法,两个方法是不一样的

  • 所以父类实例初始化完成,输出:9、3、2
  • 子类实例初始化完成,输出:9、8、7
  • sonB实例初始化,由于类只初始化一次,所以不用再执行Father类和Son类初始化过程
  • sonB实例初始化同样会先执行父类实例初始化,输出:9、3、2
  • 父类实例初始化完成再执行sonB实例初始化,输出:9、8、7
记得快乐
posted @ 2022-04-08 16:32  Y-wee  阅读(354)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3