java基础之继承(二)
上篇我们介绍了java中的构造方法,了解了关键字this和super在继承中所起到的作用,this可以显式调用重载的构造方法,super可以显式的调用父类中的任意可见方法。了解方法重载和重写的区别,知道了关键字final的作用,本篇将以一段代码介绍实例化对象时内存的状态。
如果你能看懂以下代码,那本篇你就不用浪费时间了。
/*这是父类*/
public class Base {
public Base(){
print();
}
public void print(){
}
}
//这是子类
public class Child extends Base {
private int a = 2;
public void print(){
System.out.println(a);
}
}
//main函数
public class Test2 {
public static void main(String[] args){
Base b = new Child();
b.print();
}
}
输出结果:
0
2
四、new关键字的背后
我们知道在java中所有的方法都是在类中的,包括main方法。所以程序开始做的第一件事情是:加载类,就是将类的信息加载到内存中,一个类的信息主要有:
- 静态变量
- 静态初始化代码块
- 静态方法
- 实例变量
- 实例初始化代码块
- 实例方法
- 对继承自父类的信息的引用
类的加载过程如下: - 首先在内存堆中开辟内存以存放当前类
- 对类中的属性赋默认初始值(int默认为0,boolean默认为false,引用类型默认为null)
- 调用构造函数进行对象初始化(首先默认执行super调用父类构造函数)
- 父类构造函数初始化完成之后回到子类完成子类的显式初始化
- 最后将该对象赋值给引用对象
下面就介绍一下,Base b = new Child();这条语句,内存的实时状态。
内存主要有栈和堆构成,栈中主要存放局部变量,b这个引用就存放其中,堆中主要存放引用的实际内容
首先将Base加载到堆中的方法区,这就相当于一个模板,以后new对象时候就按照此模板来创建对象,然后将变量名b存放到栈中,执行new语句,发现Child类并未加载到方法区,于是加载Child类到方法区,然后根据方法区中的Child类的模板new出child类的实例对象,它具有模板中所有信息,
接着执行child对象的构造方法,默认创建父类对象并执行父类的构造方法实现父类初始化,完成之后回到子类实现子类的初始化
最终完成对象的创建,将b引用堆中对象。
以上便是Base b = new Child();背后所做的事情
五、方法调用的细节
如果没有继承的概念,方法的调用就是非常简单的,但是有了继承的概念之后,就需要搞清楚检索方法的过程,jvm是怎么找到我们想要调用的方法的,然后执行的呢?
/*这是父类*/
public class Base {
private String name = "walker";
public void sayHello(){
System.out.println("hello child");
}
public void showName(){
System.out.println("my name is " + this.name);
}
}
//这是子类
public class Child extends Base {
public void sayHello(){
System.out.println("hello child");
}
}
//调用main函数
public class Test2 {
public static void main(String[] args){
Base b = new Child();
b.sayHello();
b.showName();
}
}
输出结果:
hello child
my name is walker
这下我们从b.sayHello()说起,首先查看b的实际类型(发现是child类型),于是从child实例对象中查找此方法,找到了,然后直接执行输出hello child本条语句执行完成,接下来执行b.showName();,依然从child对象中查找,没有找到,于是jvm深入到父类对象中,找到并执行输出结果。
总结下,java中总是从当前对象的实际类型出发搜索方法,子类中没有找到的话就会深入父类中搜索,如果父类中也没有找到就会报错
之后为了改进这种搜索效率,使用了虚方法表,也就是将每个类的所有方法(包含父类的方法引用)存放到一张虚拟表中,每次调用方法时候,查找表以加快效率。
**最后我们根据以上所有内容,解析本文刚开始的一段代码。**
第一句:Base b = new Child();,加载Base类,创建局部变量b存放栈中,发现child类未加载于是去加载child类,按照以上介绍的加载过程,首先开辟了内存以存放类的内容,将private int a;初始化为0。执行new操作,并调用child类的构造方法,转去调用Base类的构造方法,调用函数print,于是判断出此对象的实际类型是child,在child类中查找print找到并执行输出还未显式初始化的a=0,然后返回Base构造方法中,结束父类构造方法,转回执行child构造方法,结束child构造方法完成属性的显式初始化,a=2,结束本条语句。
第二句:b.print();再次搜索print执行输出2,结束。
本文若有不当之处,还望大神不吝赐教,tk。
java基础之继承(二)的更多相关文章
- Java基础拾遗(二)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76358523冷血之心的博客) 马上就要秋招了,新的一轮笔试面试马上 ...
- java基础语法(二)--单列模式
java基础语法(二)--单列模式 /** * 功能:单列模式 * @author Administrator * */ public class SingletonTest { public sta ...
- 第二十八节:Java基础-进阶继承,抽象类,接口
前言 Java基础-进阶继承,抽象类,接口 进阶继承 class Stu { int age = 1; } class Stuo extends Stu { int agee = 2; } class ...
- java基础解析系列(二)---Integer
java基础解析系列(二)---Integer 前言:本系列的主题是平时容易疏忽的知识点,只有基础扎实,在编码的时候才能更注重规范和性能,在出现bug的时候,才能处理更加从容. 目录 java基础解析 ...
- java基础知识点补充---二维数组
#java基础知识点补充---二维数组 首先定义一个二维数组 int[][] ns={ {1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16} }; 实现遍 ...
- Java基础反射(二)
原文地址http://blog.csdn.net/sinat_38259539/article/details/71799078 反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Cla ...
- Java基础学习-- 继承 的简单总结
代码参考:Java基础学习小记--多态 为什么要引入继承? 还是做一个媒体库,里面可以放CD,可以放DVD.如果把CD和DVD做成两个没有联系的类的话,那么在管理这个媒体库的时候,要单独做一个添加CD ...
- JAVA基础-集合(二)
一.Map整体结构体系 Map是集合的另一大派系,与Collection派系不同的是Map集合是以键值对儿的形式存储在集合的.两个键为映射关系,其中第一个键为主键(主键是唯一的不可重复),第二个键为v ...
- Java基础学习笔记二十八 管家婆综合项目
本项目为JAVA基础综合项目,主要包括: 熟练View层.Service层.Dao层之间的方法相互调用操作.熟练dbutils操作数据库表完成增删改查. 项目功能分析 查询账务 多条件组合查询账务 添 ...
- Java基础知识点(二)
前言:Java的基础知识点不能间断. 1.Array和ArrayList的区别 关于Array的用法,参看:http://blog.csdn.net/b_11111/article/details/5 ...
随机推荐
- linkin大话面向对象--包和导入
我们现在的代码都扔在一个文件夹里面,比如以后我们做项目,是不是有可能有非常非常多的代码,那我就希望把不同功能和模块的类方便管理,放到不同的文件夹下,引出包概念. 什么是包,就一个文件目录,为了处理重名 ...
- Log4net使用详细说明
1.概述 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.本文主要是介绍如何在Visual S ...
- 看得懂的区块链,看不清的ICO人心
比特币又开始下跌了,是狂欢尽头还是又一波调整,无从得知,背后的乱象会让监管者继续心烦,而这乱象对我来说,有时候会有些心寒. 你说我怎么可能想到,我一个写程序的人,突然有一天会发现,朋友圈里有一些搞技术 ...
- template()方法
template(id, data)方法: id:必传,渲染模板的id. data:可选,一个Object对象. return:传data—>渲染完成html代码:不传data—>一个渲染 ...
- 07_Python变量内存地址、小数据池
一.变量在内存中的地址 变量:用来标识(identify)一块内存区域.为了方便表示内存,我们操作变量实质上是在操作变量指向的那块内存单元.编译器负责分配.我们可以使用Python内建函数id()来获 ...
- CentOS的软件包的管理之rpm和yum
在linux上,一个软件包通常由二进制程序,库文件,配置文件和帮助文件组成. 其中: 二进制程序一般都放在/bin,/sbin,/usr/bin,/usr/sbin,/usr/local/bin和/u ...
- 全部用startssl生成的证书,配置Apache使其支持SSL
Apache的编译安装见这篇: http://www.cnblogs.com/yjken/p/3921840.html 网上查阅了一大批资料,得知自己生成的证书是会被浏览器提示“证书不安全”的,我也就 ...
- oracle表中字段的添加、删除
在oracle数据库中为一张表添加一个字段: alter table tableName add ClIENT_OS varchar2(20) default '0' not null ; 在orac ...
- BZOJ 2986: Non-Squarefree Numbers [容斥原理 二分]
题意:求第$n \le 10^{10}$个不是无平方因子数 二分答案, 容斥一下,0个质数的平方因子-1个..... 枚举$\sqrt$的平方因子乘上莫比乌斯函数,最后求出无平方因子数的个数取补集 # ...
- Appium的iOS环境搭建
操作系统的名称:Mac OS X操作系统的版本:10.13.3 xcode 版本:9.2 java 版本:java8_161 appium destop版本:1.7.3 接下来我们开始踏上搭建Appi ...