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 ...
随机推荐
- iphone启动图UI切图尺寸对照保存
- HTML5与css3权威指南(一)
doctype声明: <!DOCTYPE html> 字符编码: <meta charset="utf-8"> 不允许写结束标记:area,base,br. ...
- Struts2中实现随机验证码
一.创建RandomNum类 1: import java.awt.Color; 2: import java.awt.Font; 3: import java.awt.Graphics; 4: im ...
- Node-debug方法
本文使用配置node-inspector配合chorme完成debug(编辑器使用SublimeText3). 1.用命令行进入安装node的目录,使用npm install -g node-insp ...
- 浅析调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException
废话不多说,直接进入正题:如何使用JSR303的validate,进行数据校验,失败后直接抛出异常加入流转信息中,并在form页面提示出来. 首先我们为了启用验证,需要向 项目中添加Bean验证的实现 ...
- Jmeter之http性能测试实战 NON-GUI模式 进行分布式压力测试——干货(十二)
Apache JMeter Distributed Testing Step-by-step This short tutorial explains how to use multiple syst ...
- java基础(一) 深入解析基本类型
. 浮点数使用 IEEE(电气和电子工程师协会)格式. 浮点数类型使用 符号位.指数.有效位数(尾数)来表示.要注意一下,尾数的最高 在java中,float 和 double 的结构如下: 类 ...
- template.compile()方法
template.compile(source, options) source:必传,渲染模板的内容. options:可选,通常不传.(其实是我还没研究明白) return:一个渲染函数. 示例如 ...
- Yii框架中使用mongodb扩展
前提条件:安装了mongodb数据库 安装了mongo的php驱动 下载Yii的mongo扩展:这是YiiMongoDbSuite的1.3.6版本支持PHP Mongo驱动的版本为1.0.5及以下 下 ...
- iOS-Xcode编码自动补全失效
1. 退出 Xcode 2. 重启电脑 3. 找到 这个 DerivedData 文件夹 删除 (路径: ~/Library/Developer/Xcode/DerivedData) 4. 删除这个 ...