详解java中继承关系类加载顺序问题

发布时间 - 2026-01-11 01:46:43    点击率:

详解java中继承关系类加载顺序问题

实例代码:

/**
 * Created by fei on 2017/5/31.
 */
public class SonClass extends ParentClass{
  public SonClass(){
    System.out.println("SonClass's constructor");
  }
  { System.out.println("SonClass's block");}
  static {
    System.out.println("SonClass's static block ");
  }

  public static void main(String[] args) {
    System.out.println("------ main start ------ ");
    new SonClass();
    System.out.println("------ main end ------ ");
  }
}

class ParentClass{
  public ParentClass(){
    System.out.println("ParentClass's constructor");
  }
  { System.out.println("ParentClass's block");}
  static {
    System.out.println("ParentClass's static block ");
  }
}

运行结果:

ParentClass's static block 
SonClass's static block 
------ main start ------ 
ParentClass's block
ParentClass's constructor
SonClass's block
SonClass's constructor
------ main end ------ 

根据运行结果,一目了然,在执行 main 方法中 new SonClass() 之前,就在类加载之后执行了类中 static 代码块。然后再进入main方法,执行new操作,当然显而易见,在执行new子类操作的时候,是要先进行其父类的构造,即先执行父类的构造代码块(代码中只用大括号包裹的那段代码)以及构造函数 ,然后再执行子类的构造代码块以及构造函数。

修改一下代码,再来看看运行的结果:

/**
 * Created by fei on 2017/5/31.
 */
public class SonClass extends ParentClass{
  ParentClass parentClass;
  public SonClass(){
    System.out.println("1");
  }
  public SonClass(String name){
    System.out.println("2");
    this.name = name;
    parentClass = new ParentClass("FEI");
  }

  public static void main(String[] args) {
    System.out.println("------ main start ------ ");
    new SonClass("fei");
    System.out.println("------ main end ------ ");
  }
}

class ParentClass{
  String name ;
  public ParentClass(){
    System.out.println("3");
  }
  public ParentClass(String name){
    System.out.println("4");
    this.name = name ;
  }
}

运行的顺序是:

------ main start ------ 
3
2
4
------ main end ------ 

第一个规则:子类的构造过程中,必须调用其父类的构造方法。一个类,如果我们不写构造方法,那么编译器会帮我们加上一个默认的构造方法(就是没有参数的构造方法),但是如果你自己写了构造方法,那么编译器就不会给你添加了,所以有时候当你new一个子类对象的时候,肯定调用了子类的构造方法,但是如果在子类构造方法中我们并没有显示的调用基类的构造方法,如:super(); 这样就会调用父类没有参数的构造方法。

第二个规则:如果子类的构造方法中既没有显示的调用基类构造方法,而基类中又没有无参的构造方法,则编译出错,所以,通常我们需要显示的:super(参数列表),来调用父类有参数的构造函数,此时无参的构造函数就不会被调用。

总之,一句话:子类没有显示调用父类构造函数,不管子类构造函数是否带参数都默认调用父类无参的构造函数,若父类没有则编译出错。

还是两个类,我们再更改一下。

/**
 * Created by fei on 2017/5/31.
 */
public class SonClass extends ParentClass{
  private String name = "SonClass";

  public SonClass() {
    printName();
  }
  public void printName() {
    System.out.println("SonClass print name: " + name);
  }
  public static void main(String[] args){
    new SonClass();
  }
}

class ParentClass{
  private String name = "ParentClass";

  public ParentClass() {
    //System.out.println(this.getClass());
    printName();
  }
  public void printName() {
    System.out.println("ParentClass print name: " + name);
  }
}

看了上面的两个例子,最后这个例子就很容易被迷惑,可能有人会觉得运行结果是类似这样的:

ParentClass print name: ParentClass 
SonClass print name: SonClass

或者是:

ParentClass print name: SonClass
SonClass print name: SonClass

但真正的结果是这样的:

SonClass print name: null
SonClass print name: SonClass

为什么会这样,其实只要打开代码中父类构造器中的这句注释,就很容易理解了:System.out.println(this.getClass())
结果是:

class SonClass

没错,父类中的this引用是子类实例对象,所以在父类构造函数里调用的还是子类的printName()方法。具体原因也并我能十分肯定,我个人浅见,是因为虽然我们调用了父类的构造方法,但是我们并没有实例化出父类的实例对象,所以this还是指向的是子类的引用。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


# java继承关系类加载顺序问题  # java继承关系类加载顺序实例详解  # java中子类继承父类  # 程序运行顺序的深入分析  # java中 IO 常用IO操作类继承结构分析  # java子类继承父类实例-披萨的选择实现代码  # java用接口、多态、继承、类计算三角形和矩形周长及面积的方法  # Java内部类的继承(全)  # JAVA 继承基本类、抽象类、接口介绍  # java类中元素初始化顺序详解  # Java类初始化和实例化中的2个“雷区”  # 解析Java虚拟机中类的初始化及加载器的父委托机制  # Java类继承关系中的初始化顺序实例详解  # 子类  # 类中  # 很容易  # 然后再  # 其父  # 的是  # 加载  # 就会  # 是因为  # 就在  # 看了  # 结果是  # 第一个  # 是这样  # 就不  # 当你  # 你自己  # 我能  # 用了  # 希望能 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何快速重置建站主机并恢复默认配置?  PHP 500报错的快速解决方法  javascript基于原型链的继承及call和apply函数用法分析  linux top下的 minerd 木马清除方法  如何快速搭建FTP站点实现文件共享?  大型企业网站制作流程,做网站需要注册公司吗?  深圳网站制作培训,深圳哪些招聘网站比较好?  实现点击下箭头变上箭头来回切换的两种方法【推荐】  Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】  魔毅自助建站系统:模板定制与SEO优化一键生成指南  Laravel如何部署到服务器_线上部署Laravel项目的完整流程与步骤  如何用已有域名快速搭建网站?  为什么php本地部署后css不生效_静态资源加载失败修复技巧【技巧】  Laravel定时任务怎么设置_Laravel Crontab调度器配置  java中使用zxing批量生成二维码立牌  谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复  HTML 中动态设置元素 name 属性的正确语法详解  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?  UC浏览器如何设置启动页 UC浏览器启动页设置方法  Laravel怎么配置S3云存储驱动_Laravel集成阿里云OSS或AWS S3存储桶【教程】  香港服务器建站指南:免备案优势与SEO优化技巧全解析  Laravel项目如何进行性能优化_Laravel应用性能分析与优化技巧大全  Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程  Laravel如何使用withoutEvents方法临时禁用模型事件  如何在IIS7上新建站点并设置安全权限?  Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】  Laravel观察者模式如何使用_Laravel Model Observer配置  焦点电影公司作品,电影焦点结局是什么?  如何在企业微信快速生成手机电脑官网?  如何在Windows环境下新建FTP站点并设置权限?  宙斯浏览器视频悬浮窗怎么开启 边看视频边操作其他应用教程  Laravel表单请求验证类怎么用_Laravel Form Request分离验证逻辑教程  Laravel如何使用Collections进行数据处理?(实用方法示例)  消息称 OpenAI 正研发的神秘硬件设备或为智能笔,富士康代工  Laravel怎么调用外部API_Laravel Http Client客户端使用  青岛网站建设如何选择本地服务器?  如何在阿里云部署织梦网站?  MySQL查询结果复制到新表的方法(更新、插入)  Laravel如何使用Blade组件和插槽?(Component代码示例)  Laravel的路由模型绑定怎么用_Laravel Route Model Binding简化控制器逻辑  深圳网站制作平台,深圳市做网站好的公司有哪些?  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  Laravel如何从数据库删除数据_Laravel destroy和delete方法区别  iOS正则表达式验证手机号、邮箱、身份证号等  大学网站设计制作软件有哪些,如何将网站制作成自己app?  Laravel如何为API编写文档_Laravel API文档生成与维护方法  Laravel Blade模板引擎语法_Laravel Blade布局继承用法  如何在不使用负向后查找的情况下匹配特定条件前的换行符  香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南  Laravel队列任务超时怎么办_Laravel Queue Timeout设置详解