java面向对象--继承与多态
可以为一个变异单元中的每个类创建一个main方法,只有命令行所调用的那个类的main方法才会被调用,这样方便进行单元测试。
继承时,一般将所有的数据成员都指定为private,将所有的方法指定为public。
当创建一个子类的对象时,该对象内部包含了一个父类的子对象(subobject??)。这个对象和用父类直接创建的对象是一样的。
关键字super并不是一个对象的引用,因为不能将super赋值给另外一个对象变量。super只是一个只是编译器调用直接父类成员变量的特殊关键字。有两种用途:一是调用父类的方法;二是调用父类的构造器。
如果父类构造器为无参构造器,子类构造器中可以不用写调用父类构造器的语句,编译器会自动加上。但是如果父类构造器有参数时,在子类构造器中必须显式的通过super(arg)调用父类的构造器,否则会报错。
子类可以override父类方法,也可以overload父类的方法。
所有的override都使用@Override注解,可以防止不想重载时而意外的进行了重载。
重写(Override)
重写是子类对父类允许访问的方法的实现过程进行重新编写。好处在于子类可以根据需要,定义特定于自己的行为。
当父类中的方法被覆盖了后,除非用super关键字,否则就无法再调用父类中的方法。
重写规则:两同两小一大。
方法名、参数列表必须相同;返回值类型和抛出的异常更小或相等;访问权限更大或相等。
声明为final的方法不能被重写;
声明为static的方法不能被重写,但是能够被再次声明;
重写的方法能够抛出任何非强制异常,不能抛出新的或更广泛的强制性异常;
构造方法不能被重写;
父类的成员方法只能被它的子类重写,如果不能继承一个方法,则不能重写这个方法;
子类和父类在同一个包中,声明为private和final的方法不可被子类重写;
子类和父类不在同一个包中,子类只能重写父类的声明为public和protected的非final方法;
被覆盖的方法不能为static,因为静态方法是在编译的时候把静态方法和类的引用类型进行匹配。
组合和继承
组合是”has-a”的关系,在新类中嵌入一个现有类的private对象,新类的用户看到的是为新类所定义的接口,而不能看到嵌入对象的方法。
extend关键字的英文意思是扩展,表明子类对父类的扩展,子类是一种特殊的父类。
继承是”is-a”的关系,使用某个现有类,并开发一个它的特殊版本。通常使用的场景:
1. 子类需要额外增加属性,而不仅仅是属性值的改变。
2. 子类需要增加自己独有的行为方式(包括增加新的方法或重写父类的方法)。
只有必须向上转型时才用继承,否则优先考虑使用组合。
向上转型
为什么需要?
子类不仅是子类的类型,而且也是父类的类型。向上转型是从一个较专用类型向较通用类型转换,一般比较安全,唯一可能反生的事情是接口变小丢失子类对父类扩展的方法。因为编译期虚拟机会预先为每个类生成方法表(父类不会具有子类的方法,但是子类会具有父类的方法),向上造型的引用变量调用子类特有的方法,会报错。
final关键字:一旦(在初始化过程中)被设置为初始值之后,就不能再改变。
final数据:static final编译时期常量,全用大写字母表示,单词间用下划线’_’分割。
对于基本类型,final使数字恒定不变;而对于对象引用,final使引用恒定不变,但引用的对象可以发生改变。
空白final:被声明为final但又未给定初值的成员变量。需确保在使用前初始化。
final参数:无法在方法中更改参数引用所指向的对象。
final方法:确保在继承中方法行为保持不变,并且不会被覆盖或修改。
类中所有的 private 方法都隐式地是 final 的。
final类:不允许做任何变动,没有子类,所以方法也隐式地为final的。
不可变类(immutable):创建该类的实例之后,该实例的属性是不可变的。如果不可变类包含引用类型的属性,可以在内部重新构建一个一模一样的对象赋值给引用,使引用脱离外部影响。
多态
相同类型的父类引用变量,执行同一个方法时呈现出不同的行为,这就是多态。
“封装”通过合并特征和行为来创建新的数据类型。“实现隐藏”则通过细节私有化将接口和实现分离开来。而多态的作用则是消除类型之间的耦合关系,将多种子类型视为同一父类型进行处理(父类型的引用变量可以引用不同子类型的对象),这样同一份代码可以毫无差别地运行在这些不同子类型上,不用为每一个子类型重复定义相同逻辑的处理方法。
多态用父类型引用调用相应的方法,如何确定是哪个具体子类型呢?
绑定指的是将一个方法的调用与方法的主体关联起来java中,绑定分为静态绑定和动态绑定(dynamic binding),或者叫做前期绑定(early binding)和后期绑定(late binding)。
静态绑定:在程序执行前方法已经被绑定(也就是说在编译过程中就已经知道这个方法到底是哪个类中),此时由编译器或其它连接程序实现。
在java中可以简单理解为程序编译期的绑定,只有被final,static,private修饰的方法和构造方法是前期绑定的,由声明的类型决定。
java的编译过程是将java源文件编译成字节码(jvm可执行代码,即.class文件)的过程,在这个过程中java是不与内存打交道的,编译器会进行语法的分析,如果语法不正确就会报错(比如编译器只允许对象调用在类中声明的函数)。
Java的运行过程是指jvm(java虚拟机)装载字节码文件并解释执行,在这个过程才创立内存空间,执行java程序。
动态绑定:在运行时根据对象的类型进行绑定。之所以存在动态绑定,就是因为有些方法需要实例化对象后才能确定是哪个类的。
若一种语言实现了后期绑定,必须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器一直不知道对象的类型,但方法调用机制能找到正确的方法主体并加以调用。
动态绑定的过程:
虚拟机提取对象的实际类型的方法表(虚拟机预先为每个类创建的表,列出了所有方法的签名,以后方法调用时就无需搜索,只要查表就性);虚拟机搜索方法签名;调用方法。
动态绑定的特性:无需对现存的方法代码进行重新编译就可以对程序进行扩展。
动态绑定的典型发生在父类和子类的转换声明之下:Parent p = new Child();
注意:运行时(动态)绑定针对的范畴只是对象的方法,类中的成员变量(实例变量和类变量)是一般意义上的静态绑定,由编译器解析,只能访问引用变量类型所具有的属性。所以在向上转型后,父类的引用调用哪个子类型的方法由子类型对象决定,而访问对象属性时,系统总是访问它编译时类所定义的属性,即由向上造型后的父类型引用决定(子类对父类成员变量的隐藏)。
重载的方法签名是完全不同的,所以静态绑定就可以确定到底是哪个方法了;而重写的方法签名是可以和超类一样的,需要实例化对象之后才能确定是哪个类中的方法。
super.getClass().getName() //返回当前子类的类名
package demo3;
class Super {
public int field = 0;
public int getField() {
return field;
}
} class Sub extends Super {
public int field = 1;
public int getField() {
return field;
}
public int getSuperField() {
return super.field;
}
} public class FieldAccess {
public static void main(String[] args) {
Super sup = new Sub(); // Upcast
System.out.println("sup.field = " + sup.field + ", sup.getField() = " + sup.getField());
Sub sub = new Sub();
System.out.println("sub.field = " + sub.field + ", sub.getField() = " + sub.getField()+ ", sub.getSuperField() = " + sub.getSuperField());
}
}
/*
* Output: sup.field = 0, sup.getField() = 1 sub.field = 1, sub.getField() = 1,
* sub.getSuperField() = 0
*/// :~
向下转型
父类型的引用变量转向更具体的子类型,不安全,有可能会导致ClassCastExecption。转型之前先用instanceof 关键字判断一下。
instanceof:is a runtime check,判断前者引用变量是否是后者实现类或接口的实例,通常instanceof前后的操作数有实现或继承关系,否则在编译时就会出错,而不会等运行时再返回false,效率更高。
new Date() instanceof String;// Incompatible conditional operand types Date and String
super和this的区别
1)super(参数):子类调用父类的某一个构造函数(应该为子类构造函数中的第一条语句)
2)this(参数):调用本类中重载的构造函数(应该为构造函数中的第一条语句)
3)super: 基类与派生类中有相同成员定义时,用来访问当前对象的直接父类中的成员(即访问直接父类中被隐藏/覆盖的成员数据或方法)。如:super.属性名,super.方法名。
4)this:它代表当前对象的引用(如果函数的形参与类的属性同名,这时需用this来指明对象的属性)
5)调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super()。
6)尽管可以用this调用一个构造器,但却不能调用两个。
7)this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
8)this()和super()都指的是对象,所以都不可以在static环境中使用。包括static变量,static方法和static语句块。
9)从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。
java面向对象--继承与多态的更多相关文章
- Java面向对象㈡ -- 继承与多态
Java的继承是通过extends和implement来实现的,Java不支持多继承,但是Java支持多层继承以及多实现(接口).Java继承有一个关键字super是用来指向父类.Java继承衍生出覆 ...
- Java面向对象 继承(下)
Java面向对象 继承(下) 知识概要: (1)抽象类 1.1 抽象类概述 1.2 抽象类的特点 ...
- Java面向对象 继承(上)
Java面向对象 继承 知识概要: (1)继承的概述 (2)继承的特点 (3)super关键字 (4)函数覆盖 (5) 子类的实例化过程 (6) final关键字 (1)继承 ...
- Java的继承和多态
看了博客园里面的一个文章,关于java的继承和多态: class A ...{ public String show(D obj)...{ return ("A and D"); ...
- [转]Java中继承、多态、重载和重写介绍
什么是多态?它的实现机制是什么呢?重载和重写的区别在那里?这就是这一次我们要回顾的四个十分重要的概念:继承.多态.重载和重写. 继承(inheritance) 简单的说,继承就是在一个现有类型的基础上 ...
- [ Java学习基础 ] Java的继承与多态
看到自己写的东西(4.22的随笔[ Java学习基础 ] Java构造函数)第一次达到阅读100+的成就还是挺欣慰的,感谢大家的支持!希望以后能继续和大家共同学习,共同努力,一起进步!共勉! ---- ...
- java中继承和多态的理解
继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父 ...
- JAVA 面向对象中的多态
多态是继封装.继承之后,面向对象的第三大特性. 现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态. Java作为面向对象的语言,同样可以描述一个 ...
- Java基础——继承和多态
面向对象的编程允许从已经存在的类中定义新的类,这称为继承. 面向过程的范式重点在于方法的设计,而面向对象的范式将数据和方法结合在对象中.面向对象范式的软件设计着重于对象以及对象上的操作.面向对象的方法 ...
随机推荐
- Async/Await替代Promise的6个理由
译者按: Node.js的异步编程方式有效提高了应用性能:然而回调地狱却让人望而生畏,Promise让我们告别回调函数,写出更优雅的异步代码:在实践过程中,却发现Promise并不完美:技术进步是无止 ...
- ORACLE JOB创建
Connected Connected as focususer SQL> SQL> --JOB 需要在命令行执行: SQL> --抽数job SQL> CREATE OR R ...
- TextView的几个属性
1. android:autoLink 自动识别文本中包含的链接,如网址.邮箱.电话.地图等:属性值有如下几种: web------------ ------只识别网址 email---------- ...
- Android -- 贝塞尔二阶实现饿了么加入购物车效果
1,上周我们实现了简单的三阶贝塞尔曲线效果实例,今天是使用二阶贝塞尔曲线加动画实现的加入购物车效果,在码代码过程中出现了些问题,过一下和大家来探讨探讨,先看一下效果图 2,从上面的效果来看我们基本上可 ...
- php最新微信扫码在线支付接口。ecshop和shopex,shopnc下完美无错
最近为客户的一个在线商城做了一个微信扫码在线支付的接口.跟大家分享一下. 1 首先可以模仿其他的接口,比如支付宝,财付通等的接口,构建模块功能文件和语言文件.2 微信提供2种扫码方式,大家可以根据自己 ...
- 【学而思】利用shouldComponentUpdate钩子函数优化react性能以及引入immutable库的必要性
凡是参阅过react官方英文文档的童鞋大体上都能知道对于一个组件来说,其state的改变(调用this.setState()方法)以及从父组件接受的props发生变化时,会导致组件重渲染,正所谓&qu ...
- 实现自动登录:Filter 实现思路和方式
当你勾选(记住登录状态),用cookie保存用户名和密码.不勾选,cookie失效. 所有的页面都要经过autoLoginFilter.java 的过滤器,在这类中,必须要判断cookies不为nul ...
- virtual box ubuntu 主机和虚拟机实现互相复制粘贴
链接:http://jingyan.baidu.com/article/574c521917db806c8d9dc18c.html 常规高级里共享粘贴板已经选中双向,(我的已经可以了复制粘贴了),如果 ...
- 深入解析Hashtable、Dictionary、SortedDictionary、SortedList
我们先看Hashtable. MSDN的解释:表示键/值对的集合,这些键/值对根据键的哈希代码进行组织. Hash算法是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定 ...
- python3和python2的区别部分
字典没有iteritems(),只有items() py2items()返回的是列表,iteritems()返回的是迭代器 py3items()返回的是迭代器