浅谈虚拟机(1)继承引发了一场血案の实例化中的继承
来源:互联网 发布:2016中国经济数据 编辑:程序博客网 时间:2024/06/05 17:52
本文要讲的是继承问题,是java基础部分,但又是面向对象的核心知识。许多初学者在理解继承和多态的时候容易记忆混淆,知识点不清晰,本文将会在一定程度上梳理继承的问题。
为什么说:继承引发了一场血案?原因是博主本来只是想写一个继承的小调试博客,但是发现要想把继承讲清楚,就不得不深入到JVM中去,而JVM内容繁多,要从JVM中讲述清楚继承,不是一篇博客就可以完成的。为了能够完成这个伟大目标,博主重新梳理JVM知识,再翻阅各种书籍查阅各方言说,进行汇总、提炼、形象化展示,期望能呈现出一个精彩的JVM世界来。其过程可谓是呕心沥血、鞠躬尽瘁、废寝忘食、闻鸡起舞、夜以继日、唧唧复唧唧……实则是一场无声的血案。
经上述吐槽后,我们先来看看浅谈虚拟机系列第一篇,血案的开始。
首先来看三段代码。
父类:
public class Father{private String name = "My name is David Beckham";//大卫贝克汉姆public Father(){System.out.println(this.name);}}
子类:
public class Kid extends Father{private String name = "My name is Brooklyn Joseph Beckham";//贝克汉姆大儿子布鲁克林public Kid(){System.out.println(this.name);}}
主线程:
public class Test{public static void main(String[] args){Kid k= new Kid();return;}}
输出结果:
My name is David BeckhamMy name is Brooklyn Joseph Beckham
以上代码只是简单地展示了类实例化的顺序,先实例化父类,再实例化子类。默认调用为无参构造函数。那么父类的实例化具体是在子类中哪一行开始的呢?通过以下代码来看
父类:
public class Father{private String name = "My name is David Beckham";//大卫贝克汉姆public Father(){System.out.println(this.name);}public Father(String s){//新增加的含参构造函数System.out.println(this.name + s);}}
子类:
public class Kid extends Father{private String name = "My name is Brooklyn Joseph Beckham";//贝克汉姆大儿子布鲁克林public Kid(String s){//传入字符串数组" love football!"System.out.println(this.name + s);}}
主线程中把Kid kid = new Kid();改为Kid kid = new Kid(" love football");
输出结果:
My name is David BeckhamMy name is Brooklyn Joseph Beckham loves football!
从这个case可以看到,子类依旧调用父类的无参构造函数。而调用位置具体是在子类构造函数被调用之前还是之后?为了解答这个问题,将在子类中显示调用父类构造函数。在子类构造函数第一行加上super(s),如下:
public Kid(String s){super(s);System.out.println(this.name + s);}
输出结果:
My name is David Beckham loves football!My name is Brooklyn Joseph Beckham loves football!
从以上可以看出。类的实例化将先实例化父类,而父类构造函数被调用的地方在子类被调用构造函数的第一行。默认调用父类的无参构造函数。当父类没有无参构造函数而又没有显示给出正确的父类构造函数调用的话,会出现如下报错:
未定义隐式超构造函数 Father()。必须显式调用另一个构造函数
在此提及下关于向上向下转型的理解,很多developer对此的理解方式是硬背,但是总会混淆。从这个地方来理解,由于父类在子类的构造函数第一行被实例化,因此一个声明为父类的引用指向子类,可以指向子类中的实例化父类对象从而得到初始化,而不会出现空指针的Exception违例。
反过来,子类的引用指向父类,由于父类没有初始化子类,因此会出现空指针的报错。
- 浅谈虚拟机(1)继承引发了一场血案の实例化中的继承
- WSAPoll引发的一场血案(1)
- WSAPoll引发的一场血案(2)
- 记:由opencv中的waitkey引发的一场血案
- 一场precision引发的血案
- SwipeRefreshLayout 引发的一场血案
- 浅谈C++中的继承
- PHP队列--选举引发的一场血案
- 由"@id/myid"引发的一场血案
- 一场.user.ini引发的血案
- 一场Socket四次握手引发的血案
- 一场Socket四次握手引发的血案
- Gitlab:一场“删库”血案引发的反思
- JavaScript_ECMAScript 继承机制实例浅谈
- 浅谈C#中的实现继承
- 浅谈Objective-C中的继承
- 浅谈C++中的虚继承
- 【C++】浅谈C++中的继承
- The current branch is not configured for pull No value for key branch.master.merge found in config
- mitmproxy使用python脚本定制开发(三)
- 《Spring Cloud与Docker微服务架构实战》内容介绍
- Calendar.getInstance()中的getInstance()函数
- android基础知识再学习
- 浅谈虚拟机(1)继承引发了一场血案の实例化中的继承
- Java中不同的并发实现的性能比较
- 151. Reverse Words in a String
- edittext显示html格式化的内容,修改内容后 获取带html格式的内容并上传到服务器
- ECMAScript和JavaScript的关系
- html元素的组合
- i2c-tools 测试i2c
- wget下载一个目录
- 测试一个进程的运行时间