三、读第八、九章
来源:互联网 发布:身份证人脸比对知乎 编辑:程序博客网 时间:2024/05/17 01:34
1、动态绑定或运行时绑定:在运行时根据对象的类型进行绑定。
2、final声明方法:除了防止被覆盖外,更重要的一个功能是可以有效地“关闭”动态绑定,告诉编译器不需要对其进行动态绑定。编译器可以为final生成更有效的代码,但是对整体性能不会有改观的,所以要根据设计决定是否用final,而不是出于试图提高性能的目的使用final.
3、private方法被自动认为是final方法,所以是不能被重写的。
4、关于多态,不是什么都可以发生多态的,只有普通方法调用可以是多态的。
如果是直接访问一个域:
父类:
public class Super { public int field = 0; public int getField(){ return field; }}
子类:
public class Sub extends Super{ public int field = 1; public int getField(){ return field; } public int getSuperField(){ return super.field; } public static void main(String[] args) { Super sup = new Sub(); System.out.println("super.field="+sup.field);//0 System.out.println("super.getField="+sup.getField());//1 Sub sub = new Sub(); System.out.println("sub.field="+sub.field);//1 System.out.println("sub.getField="+sub.getField());//1 System.out.println("sub.getSuperField="+sub.getSuperField());//0 }}
结果是:
//这讲究比较奇怪了super.field=0super.getField=1//下面这个不奇怪sub.field=1sub.getField=1sub.getSuperField=0
正如上面所述,只有普通方法调用才可以是多态,那么父类中的 getField() ,子类中的 getField() 、 getSuperField() 都是普通的方法, 但是 public int field = 1; 和 public int field = 0; 是普通的域,是不具备多态的,所以执行 sup.field 的时候,它虽然是父类指向子类,但是调用的仍然是自己的域,所以答案仍然是0;但是下面调用的方法,其实是多态,调用的是子类的方法,所以值是1.
当然这种情况几乎看不到,因为一般定义属性都是private,根本是无法访问到的。
5、关于静态方法,也不具备多态。只要是调用static 方法,就仍然调用本身,普通方法的话就调用子类的重写方法了。
6、构造器的调用顺序:
调用基类构造器—按声明顺序调用成员的初始化方法—调用导出类构造器的主体
7、关于继承和清理
子类覆盖父类的清理方法的时候,必须在后面调用父类的清理方法。
初始化的顺序是从父类开始初始化,然后子类;但是清理的时候先清理子类,再清理父类。
8、构造器内部的多态方法的行为
问题:如果在一个构造器的内部调用正在构造的对象的某个动态绑定方法,会发生什么?
public class Glyph { void draw(){ System.out.println("Glyph.draw()"); } Glyph(){ System.out.println("before deaw()"); draw(); System.out.println("after deaw()"); }}
public class RoundGlyph extends Glyph{ private int radius = 1; RoundGlyph(int r){ radius = r; System.out.println("RoundGlyph.RoundGlyph(),radius="+radius); } void draw(){ System.out.println("RoundGlyph.draw(),radius="+radius); } public static void main(String[] args) { new RoundGlyph(5); }}
执行结果是:
before deaw()RoundGlyph.draw(),radius=0 //重点after deaw()RoundGlyph.RoundGlyph(),radius=5
按照顺序,new子类的时候,首先是初始化基类。这里就直接从基类的构造器开始初始化,当执行draw()的时候,由于这个方法是一个动态绑定的方法(子类中有重写),那么它会向外深入到继承层次结构内部,调用子类的方法,那么这个时候会去调用子类中的draw(),因为这个时候radius还没有初始化,那么在类中他默认是0,所以显示出0这句。
所以,要避免这种写法,因为会被覆盖,得出意想不到的结果。
那么从这个程序来看,初始化的实际过程是:
1、在其他任何事情发生之前,将分配给对象的存储空间初始化为二进制的零。2、如前述那样调用基类构造器,调用被覆盖后的draw()方法(在子类的构造器之前使用)3、按照生命的顺序调用成员的初始化方法4、调用导出类的构造器实体
9、第九章:接口和抽象类
这位大神总结的很好: http://blog.csdn.net/chenssy/article/details/12858267
- 三、读第八、九章
- 第八,九章
- CSAPP 第八、九章
- PHP 第八,九,十章
- 周志华机器学习读后总结 第八、九章
- 第七周项目三——第八,九章思维导图
- 第八九周第六章指针
- Javascript高级程序设计第八九章
- 第八章 用户界面(三)
- 第八章 启动与执行业务流程(九)
- 4、王爽《汇编语言》笔记_第八九章
- 《JAVA并发编程实践》学习笔记(第八.九章)
- Ajax - 基础教程第八章例子学习三
- 第八周 任务三
- 第八周 任务三
- 第八周任务三
- 第八周任务三
- 第八周任务三
- [DL]基于Pytorch的Linear classified model
- Java 中的调试
- JAVA必背面试题和项目面试通关要点
- 智能家居标准ZHA
- 拷贝工具BeanUtilsBean扩展
- 三、读第八、九章
- Spring Boot整合Morphia访问MongoDB
- MQ入门总结(三)ActiveMQ的用法和实现
- LiteORM框架导入Android Studio步骤简介
- 路径正确但是还是404
- eclipse web项目跨域问题解决
- 从0开始用shell写一个tomcat日志清理脚本
- awk命令详解
- vue-router 不能判断页面是否是返回