JAVA的接口与继承
继承
在Java中,使用extends关键字实现继承,extends后跟的是父类名,也就是它从哪个类继承过来的,而用extends的这个类本身称为子类。
<--more-->--more-->
子父类构造函数详解
当一个类继承了某个类时,在子类的构造方法里,super()必须先被调用;如果你没有写,编译器会自动调用super()方法,即调用了父类的构造方法;
这并不是创建了两个对象,其实只有一个子类Sub对象;之所以需要调用父类的构造方法是因为在父类中,可能存在私有属性需要在其构造方法内初始化;
当编译器自动插入父类构造方法的调用后,子类的构造方法类似如下代码:
例如:public zi() {
super();//注意,如果不写这个,系统也会自动默认补上。
System.out.println("zi");
}
this()函数和super()函数都必须在第一行,所以出现this就没有super,反之亦然
重写
简单来说就是,如果子类方法名和父类方法名相同,那么子类就不能继承父类的方法,此时称子类的方法重写了父类的方法。重写也可称为覆盖。
super关键字
子类可以调用父类声明的构造方法,但是必须在子类的构造方法中使用super关键字来调用;如果想在子类中操作父类中被隐藏的成员变量和被重写的成员方法,也可以使用super关键字。这些在以后的项目中会出现,这里就不举例了,如果使用Java编译器的话,需要使用super关键字但未使用时编译器会有错误提示。
接口
Java语言只支持单重继承,不支持多继承。这句话的意思就是一个类只能有一个父类,但我们经常需要使用多继承来解决问题,所以Java语言提供了接口来实现类的多重继承功能。
Java中使用interface来定义一个接口,接口定义与类相似(类的定义用的是class)
接口的实现
接口的实现类需要使用implements关键字,一个类可以实现多个接口,写法就是implements后的接口间以“,”隔开即可。如果变量冲突,则通过“接口名.变量”来明确指定变量的接口。
多态
在Java中,通常使用方法的重载和重写实现类的多态性。
重写在上面已经介绍过了,而方法的重载是指在一个类中出现多个方法名相同,但参数个数或参数类型不同的方法
1,变量:
子父类中有重名变量,多态调用时,
只看调用该成员变量的引用所属的类中的成员变量!
例如: fu有num=4,zi有num=6。
fu f = new zi();
那么输出f.num的值为4。
如果fu没有num,则无法编译成功!!!!
总结:无论编译还是运行都看等号左边的。
2,函数:
子父类中有重名函数,多态调用时,
fu f = new zi();
编译时,看的是引用变量所属的类中的方法。
运行时,看的是对象所属的类中的方法。
总结:编译看左,运行看右
3,静态函数:
子父类有重名函数,多态调用时,
编译和运行都看引用变量所属的类中的方法。
总结:编译运行都看等号左边的。
多态:父类的引用或者接口引用指向了子类的对象
多态的转型
一.向上转型
{
好处:隐藏了子类型,提高了扩展性。
弊端:只能使用父类的功能,不能使用子类的特有功能。
*如果不需要面对子类型,同时提高扩展性,或者使用父类的功能即可完成操作,就 使用向上转型
}
二.向下转型
{
好处:可以使用子类型的特有功能。
弊端:必须面对具体的子类型。
*向下转型有风险,容易发生classcastException,只要转换类型和对象类型不匹 配就会发生!!!!
所以需要使用 Instanceof
例如: 对象 instanceof 类型
}
话不多说,直接来一道我学习过程中受益很大的一道题1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34public class DispatchTest {
public static void main(String[] args) {
fu b = new zi();
System.out.println(b.x);
}
}
class fu {
int x = 10;
public fu() {
this.printMessage();
x = 20;
}
public void printMessage() {
System.out.println("fu.x = " + x);
}
}
class zi extends fu {
int x = 30;
public zi() {
this.printMessage();
x = 40;
}
public void printMessage() {
System.out.println("zi.x=" + x);
}
}
打印结果为
zi.x=0
zi.x=30
20
解析
这里就要谈到JAVA类中属性的构造了,首先new zi类以后,zi类调用了super构造函数,
然后fu的构造函数被调用,初始化了父类所属的x为10(注意,此处的原理并不是父类
x还未赋值!),紧接着调用了zi类中的printmessage函数,原因是因为继承关系中,
子类的函数功能会覆盖掉父类的同名函数,而属性并不会被覆盖(也就是说x变量并不是
被覆盖,而是堆内存中出现了两个,一个是this.x,一个是super.x),所以第一个打印
结果是zi.x=0说明调用的是zi的打印函数,此处打印的值也是this.x,也就是还没有初始化的zi类x,所以是0。第二个就好理解了,在super构造结束后开始子类初始化,此时
zi类的x被赋值为30了,所以打印出30。最后一处打印出20的原因是因为,fu的构造函数
最后一步将20赋值给了super.x,然后因为多态中用的是 fu b = new zi(),所以b是fu类
的,要打印fu的x就应该找到super.x,所以打印出20。