------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
继承 class 子类名extends 父类名{}
继承的好处:提高代码复用性;提高代码维护性;类之间产生关系,多态的前提。
继承的特点:只支持单继承;支持多层继承
子类可以使用父类所有的非私有成员
子类不能继承父类的构造方法,但是可以通过 super 访问
super 关键字父类存储空间的标识
在子类中,访问父类的成员, super.父类成员,不能写在静态里面
继承中构造方法的关系
子类中所有的构造方法都默认会访问父类中空参数的构造方法
子类构造方法的第一行,有一条默认的隐式代码 super(); 调用父类空参数的构造方法
考虑到父类中成员变量的赋值情况,父类构造器没有对成员变量进行赋值,父类中重载的构造方法可以在子类中对 super() 传参数调用,即子类初始化之前要先完成父类初始化
*父类中没有默认的空参构造方法,子类构造方法中必须手动写 super() 指定参数列表
构造方法第一行,this() 和 super() 只能写一个
this 和 super 用法的区别
this 指本类对象的引用,super 父类存储空间标识
访问成员变量:
this.成员变量 super.成员变量
访问构造方法
this(); 用于本类构造方法之间互相调用
super(); 子类的构造方法默认访问父类中空参的构造方法
访问成员方法
this.成员方法 super.成员方法
子父类中静态代码块、构造代码块、构造方法的执行顺序
class Fu {
static {
System.out.println("静态代码块Fu");
}
{
System.out.println("构造代码块Fu");
}
public Fu() {
System.out.println("构造方法Fu");
}
}
class Zi extends Fu {
static {
System.out.println("静态代码块Zi");
}
{
System.out.println("构造代码块Zi");
}
public Zi() {
System.out.println("构造方法Zi");
}
}
Zi z = new Zi();
A. 静态随着类的加载而加载
B. 静态代码块 -- 构造代码块 �C构造方法
C. 只要有继承关系,先初始化父类的数据,再初始化子类数据
结果:
静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi
继承中成员方法的关系
子类重写父类的方法,权限必须大于等于父类方法的权限,剩余方法声明部分须和子类一致
静态方法严格意义上没有重写,如果静态方法被覆盖,则子类中的方法也是静态的
final 关键字
修饰类,类成为最终类,不能被继承,没有子类
修饰成员方法,方法成为最终方法,不能被子类重写,可以调用
修饰成员变量,成员变量在堆内存中有默认值
final 固定的是成员变量的手动赋值,而不是默认值
构造方法可以对成员变量初始化赋值,但是普通方法不可以对 final 成员变量赋值
因为构造方法是运行在对象建立过程中,普通方法调用时,对象已经建立完成了
多态性
多态前提和体现:继承、方法重写,父类引用指向子类对象(反之不行)
多态的好处:程序的扩展性提高,父类固定不变子类是可以无限扩展的;维护性提高
多态的弊端:不能访问子类的特有功能
多态的意义:一个类型的引用在指向不同的对象时会有不同的实现;
同样一个对象,造型成不同的类型时,会有不同的功能。
多态调用中编译和运行时期的特性:
非静态成员变量、静态成员变量:
编译时期,看父类中有没有这个变量,有编译成功,没有编译失败
运行时期,运行的是父类中的成员变量
非静态成员方法:
编译时期,看父类中有没有这个方法,有编译成功,没有编译失败
运行时期,运行的是子类重写后的方法
静态成员方法:
编译时期,看父类中有没有这个方法,有编译成功,没有编译失败
运行时期,运行的是父类中的方法(所以说静态方法不能算方法的重写)
总结:除非静态的方法以外,编译和运行都看父类;
只有非静态的方法,编译看父类,运行看子类。
多态调用中,方法必走子类重写
编译看左边,运行看右边
Fu f = newZi();
多态中的转型问题(孔子装爹案例)
向上转型:父类类型的引用指向子类对象;接口引用指向其实现类的对象
Java编译器根据类型检查调用方法是否匹配
向下转型(强制转型):
可以通过强制类型转换将父类型变量转换为子类型变量,前提是该变量指向的对象确实是该子类类型。
也可以通过强制类型转换将变量转换为某种接口类型,前提是该变量指向的对象确实实现了该接口。
如果在强制转换过程中出现违背上述两个前提,将会抛出ClassCastException
instanceof 关键字
为避免在强转中出现 ClassCastException 异常,可以通过 instanceof 关键字判断某个引用指向的对象是否为指定类型。
/*
* 孔子装爹案例--多态中的转型问题
*/
publicclassKongZiDemo {
publicstaticvoid main(String[] args) {
// 多态调用:父类引用 = 子类对象
// 子类提升为父类的类型,自动转换,向上转型
KongZiDiekd = newKongZi();
kd.teach();
System.out.println(kd.age);
System.out.println("-------");
// 多态:不能使用子类特有功能
// 使用子类特有,强制类型转换,已经提升为父类类型的子类对象,转回子类类型
KongZik = (KongZi) kd; // 类型的向下转型
k.playGame();
System.out.println(k.age);
}
}
class KongZiDie {
intage = 70;
publicvoid teach() {
System.out.println("讲做官");
}
}
class KongZi extends KongZiDie {
intage = 40;
publicvoid teach() {
System.out.println("讲论语");
}
publicvoid playGame() {
System.out.println("玩游戏");
}
}