C类继承了A和B类,创建了C对象,调用show方法,但是A和B中都有show方法,这时就不知道调用哪个类的show方法。
所以Java不直接支持多重继承的原因就是:会产生调用的不确定性。
4,Java支持多层继承
如:C extends B , B extends A,这样会出现继承体系。
当要使用一个继承体系时:
(1)查看该体系的顶层类,了解该体系的基本功能。
(2)创建该体系的最子类对象,完成功能的调用。
Java中的多继承是通过多实现的方式体现出来的,也就是通过接口的方式体现。
5,什么时候定义继承呢?
当类与类之间存在着所属关系的时候,就定义继承。
Xxx是Yyy的一种。Xxx extendsYyy。
所属关系就是is a的关系。
8-9,子父类中成员变量的特点:
1,特点:
(1)成员变量
(2)成员函数
(3)构造函数
2,当本类的成员和局部变量同名用this区分。
当子父类中的成员变量同名时用super来区分。
This:代表一个本类对象的引用。
Super:代表一个父类空间,不代表父类对象,因为不用创建父类对象就可以用super引用父类。
例如:
class Fu {
int num = 4;
}
class Zi extends Fu {
int num = 5;
void show() {
System.out.println(this.num + "..." + super.num);
}
}
class Demo {
public static void main(String[] args) {
Zi zi = new Zi();
zi.show();
}
}
结果:5...4
上例的内存图解:
首先主类Demo加载进内存,将方法加载进方法区,main加载进静态方法区(没有画出)。
然后main函数进栈,局部变量z进栈。
在堆中创建Zi的对象,JVM发现这个Zi类有个父类Fu,所以先加载其父类,先将父类的成员变量加载到Zi的单独的一片空间中,先加载父类是因为子类要用到父类的内容,那么父类就必须先初始化,否则子类无法使用。
然后将这个地址引用赋给main中的z,z指向堆内存的对象。
调用show函数,先在Zi的方法区中找这个方法,找到了,直接进栈执行,执行完毕之后,弹栈。
注意:如果这个show不是定义在子类,而是定义在父类中,那么上面这一步在Zi类方法区中是找不到show方法的,他就会通过Zi中的super引用去父类中找,如果找到,则执行,如果还没有,会到Object中找(所有类都继承自Object),如果有则执行,如果还没有,则报NoSuchMethod没有这个方法异常。
通过这个分析可以看出,super并不是指向的对象,而只是子类对父类的一个指向而已。
8-10,子父类中成员函数的特点-覆盖
1,当子父类中出现成员函数一模一样的情况,会运行子类的函数。
这种现象,称为覆盖操作,这是函数在子父类中的特性。
2,函数的两个特性
(1)重载:在同一个类中。
(2)覆盖:在子类中,也成为重写,覆写。
3,覆盖注意事项
(1)子类方法覆盖父类方法时,子类权限必须要大于等于父类的权限。
(2)静态只能覆盖静态,或被静态覆盖。
如果父类方法为private,则子类无法对这个方法进行覆盖,因为私有化以后子类将无法看到这个方法,就谈不上覆盖了。
8-11,覆盖的应用
什么时候使用覆盖操作?
当对一个类进行子类的扩展时,子类需要保留父类的功能声明,但是要定义子类中该功能的特有内容时,就是用覆盖操作完成。
class Phone {
void call() {}
void show() {
sop("number");
}
}
class NewPhone extends Phone {
void show() {
sop("name");
sop("pic");
super.show();
}
}