一、day12复习部分
1. 面向对象的三大特征:封装,继承,多态
(1)封装:保护性和易用性
(2)继承:提高代码的复用性,方便进行子类,子功能的拓展,将所有共性的内容放在父类,子类只需要关注子类独有的属性和方法
A. 要使用继承,必须满足is a 原则
例如:Dog is an animal
Cat is an animal
B. 使用extends关键字表示继承父类
C. 继承分为显示继承和隐式继承
a. 隐式继承:父类中的private域,子类实际上也继承下来了,属于隐式继承,无法直接使用
b. 显示继承:父类中的public, protected等域,属于显示继承,子类中可以直接使用
D. super关键字
a. super修饰属性:表示直接从父类中寻找同名属性
b. super修饰方法:
<1>super修饰构造方法
在实例化子类对象的时候,先调用父类的构造方法产生父类对象,而后使用子类构造方法产生子类对象
若父类中只有无参构造,则子类构造方法中可以省略super();
若父类中只有有参构造,则子类构造方法首行必须显示调用super(参数);表示调用父类的构造方法(注:一般在继承关系的子类中只保留super的首行调用,不会出现this修饰构造方法)
<2>super修饰成员方法:表示直接从父类中寻找同名方法
c. this可以表示当前对象的引用,但是super不能直接指代父类对象
2. 包访问权限 default
(1)权限修饰符不写,默认是包权限。
(2)当前包的内部且同级目录下可见,子包都不可见
(3)JDK中常用的包
java.lang java.util java.sql java.net java.io
二、封装和包作业
1. 例题1
解析:答案为C。name属性在父类中是private权限,因此属于隐式继承,子类中无法直接使用
2. 例题2
解析:
答案选c。
a. 包是一组类的集合没错
b. 不同包之间类可以同名
c. import的导入的是一个类而并不是一个包。
d. import static是静态导入,静态导入能导入方法也能导入类
3. 例题3
解析:生成子类对象的时候要先生成父类对象,也就是先调用父类的构造方法,再调用子类的构造方法 。因此答案为B
4. 例题4
解析:答案选D。父类中没有无参构造,因此子类中的构造方法中必须用super(参数)显示的调用父类中的有参构造,此题目中没有,因此编译错误
5. 例题5
解析:答案选C。
new z();要产生子类对象z必须产生父类对象x。在父类对象中Y y = new y(); 这一步实在x的构造方法中执行且优先于打印方法,因此答案为YXYZ.
注意:类属性的就地初始化实际上也在构造方法中执行,且优先于构造方法中的打印部分。
6. 例题6
解析:
答案选A
A: super是从父类中寻找同名属性和同名方法
B: this表示对当前对象的引用,super只能指代直接父类,不能指代父类的父类
CD: 子类可以通过super关键字调用父类的方法和父类的属性,因此CD都错
7. 一个额外的题目(非常重要!!!):已知下列代码,求执行顺序
(1)补充知识:
A. 什么时候加载类:用的时候加载类
B. 加载具有继承关系的子类:先加载起父类,再加载子
(2)解析
A. 主方法位于子类D中,要执行主方法首先要加载主类D,主类D继承于主类B中,因此需要先加载父类再加载子类。
加载类就要执行静态块代码,因此
3 6
B. 主方法内第一句执行7
C. 之后产生对象:构造块优先于构造方法执行,父类对象创建优先于子类对象
因此顺序为
2154 2154
D. 主方法最后一句执行8
因此顺序为367215421548
二、继承收尾
1. 关于继承访问权限protected关键字:不同包的具有继承关系的类之间可见
2. 不同包的具有继承关系的类之间可见,下面是示例
(1)示例1
(2)示例2:不同包下不具备继承关系类之间不可见
3. 注意1(重中之重):
4. 在同一个包的毫无关系的不同类之间,protected修饰的属性和方法当然可见(default是同一个包内不同类之间都可见,protected权限大于default)
(1)原理
(2)示例:
5. 继承关系(注意:Java的单继承局限:一个类只能使用extends直接继承一个父类,不允许多继承,但是允许多层继承)
6. final关键字:终结器-到此为止
(1)final 修饰的属性称为常量,一旦被final修饰,则变量成为常量,一旦初始化后,数值不能修改
A. final修饰基本数据类型
B. final修饰引用数据类型
C. 总结:
D. final修饰的变量使用前必须赋值
(2)final修饰方法=>被final修饰的方法无法被重写/覆写
(3)final修饰类=>被final修饰的类不能有子类 (JDK中的String类就是final类)
7. 类和类之间的关系
(1)继承:继承表示的是类之间的is a 关系
(2)组合:组合表示的是类之间的has a关系
例如:School has a Student; School has a Teacher
(3)二者的联系:组合和继承都可以实现代码复用,到底使用继承还是组合要用上述的is a 还是 has a来判断
组合关系也可以实现代码的复用,组合类的内部包含了其他类,直接调用其他类对象的属性和方法实现代码复用
三、多态
1. 多态含义:同样一个方法/行为,经过不同的对象,表现出不同的行为,这样的现象称为多态。
两不同一相同:不同的对象调用相同的方法表现出不同的行为,称为多态性
例如:
2. java中要想实现多态,必须同时满足一下三个条件
(1)多态的实现必须依赖于继承,在继承体系下才有多态。只有在继承关系的类之间才有多态
(2)子类必须要覆写父类中的方法
(3)通过父类的引用调用子类重写的方法
以下是多态实例
3. 方法重写(override)
(1)定义:
A. 在有继承关系的类之间,
B. 子类定义了和父类除了权限不同以外,(权限:子类重写方法的权限>=父类方法,父类方法权限>private)
C. 其他(方法名称,参数列表,返回值类型(向上转型类除外))全部相同的方法,称为子类重写了父类的方法。
(2)对比方法重载(overload):在同一个类中,定义了一组方法名称相同,参数列表(个数和类型)不同的,与返回值无关的一组方法,称为重载方法。(重载不需要考虑权限,因为都在一个类中,即便最小的private权限也是当前类内部可见)
(3)方法重写的权限问题,以实例说明
A. 例子:子类Teddy覆写了父类Dog中的bark方法。若父类是public,则子类也必须是public
B. 若父类是deafult,在子类可以是deafult,proctected, public
(4)方法重写不包含私有方法的重写!私有继承,子类根本不知道父类存在这个私有方法。所谓的重写,即为在父类现有方法上进行覆盖,因此能够方法重写的前提是子类能够看得见父类中需要重写的方法
父类中用private
子类中用其他
(5)static方法不能重写
原理:重写是为了多态服务的,多态是不同的对象调用相同的方法呈现出不同的行为,也就是重写方法和具体对象有关。而static方法和类强相关和具体对象无关,因此不存在重写
(6)构造方法不能被重写
重写相当于在子类中,改变了父类的方法行为,以当前子类的方法行为为准
构造方法是初始化对象的属性的,假设构造方法能够被重写,相当于在子类中改变了父类构造方法的行为,相当于在子类中决定了父类对象的产生
(7)重写的作用
(8)一组概念
A. 动态绑定——方法重写:编译时无法确定到底调用的是哪个对象的方法,只有在运行时,根据具体传入fun的对象,才能知道到底调用的是哪个对象的方法,这就叫做动态绑定。即运行时明确调用的是哪个方法
B. 静态绑定——方法重载:编译时,编译器根据用户传参的不同决定到底调用哪个方法
(9)向上转型(天然发生,也是产生对象的主要使用方式)
A. 语法
父类名称 父类引用 = new 子类构造方法(参数);
例如:Animal animal = new Dog("66", 6);
B. 如何确定是不是向上转型,代码从右往左读,如果满足继承关系的is a 原则,即为天然的向上转型
例如:Animal animal = new Dog("66", 6); //dog is an animal,因此是天然的向上转型
C. 原理
D. 向上转型的调用规则:
a. 父类引用决定能调用什么:到底通过这个父类引用能够调用哪些属性和方法,看父类中有哪些属性和方法
b. 子类决定方法表现的具体行为:调用的方法到底表现出什么行为,看到底new的是哪个子类对象。若该子类对象覆写了父类的方法,则调用的是子类覆写后的方法,否则调用的是父类中的方法
实例如下
E. 向上转型带来的程序上的优势:参数统一化
例子:
a. 若不存在向上转型,引用只能指向当前类型的对象
则需要定义N个重载fun方法,参数的类型不同,用于接收不同类型的对象,如下图代码
缺点:每当产生一个新的子类都需要重载一个对应的fun方法。出现大量的代码冗余;不方便子类的拓展。
b. 存在向上转型好处,
则
如下面代码所示
(10)向下转型(大类型转换为小类型,需要强制类型转换,要发生向下转型,一定先发生向上转型)
A. 向上转型的存在的问题引出向下转型
问题:向上转型只能调用父类中存在的方法,子类中独有的方法无法通过向上转型的父类引用调用。这个问题需要通过向下转型来解决。
B. 语法:
注意: 向下转型当且仅当存在继承关系的类之间才能转换成功,否则会转换失败
子类名称 子类引用 = (子类名称和前面一致) 父类引用(向上转型后的父类引用)
例如:Dog dog = (Dog) animal; //
C. 实例
D. 实例2:转换失败,编译时不会报错,运行时会报类型转换异常
(11)instanceof关键字:用来判断一个引用是否指向一个子类实例,返回值为布尔类型
A. 语法:
引用名称 instanceof 子类
B. 应用:可以用来判断一个父类引用是否指向一个子类实例,来判断是否能进行向下转型
C.示例