java中只支持单继承不支持多继承。
有些语言是支持多继承的,格式:extends类1,类2...
但是java支持多层继承,例:子类继承父类,父类也可以继承父类的父类(此处形象称为:爷爷类),子类同样拥有爷爷类的属性和方法
案例:
“爷爷类:”
package day08;
public class GrandFather {
public void show(){
System.out.println("我会唱戏!");
}
}
“父亲类”package day08;
public class Father extends GrandFather {
public void play(){
System.out.println("我会开车!");
}
}
子类:package day08;
public class Son extends Father {
}
测试类:package day08;
public class SonMain {
/**
* @param args
*/
public static void main(String[] args) {
// 创建son类对象
Son s = new Son();
//调用父类Father的play()方法
s.play();
//调用父类的父类GrandFather的show()方法
s.show();
}
}
输出:
我会开车!
我会唱戏!
1-子类只能继承父类所有的非私有成员(方法和变量),不能继承父类的私有成员。
2-父类的构造方法不被子类所继承,但是可以通过super关键字访问父类构造方法,以及操作父类成员。
注意:子类虽然不能继承父类的构造方法,但是子类在实例化对象(不管对象有无参数)的时候会自动调用父类的无参构造方
法。
首先要思考类与类之间的关系:是否具有附属关系。
例:
人类:
学生类
老师类
水果类:
苹果类
西瓜类
香蕉类
继承中成员变量之间的关系:(一层父类情况下)
1-如果子类中成员变量名称和父类中成员变量名称不一样,可以很方便的调用。
2- 如果子类中成员变量名称和父类中成员变量名称一样,则要注意调用顺序:
1- 首先在子类的方法的局部范围查找,有就调用使用
2-然后在子类成员范围查找,有就调用使用
3-然后在父类成员范围查找,有就调用使用
如果都没找到,就会报错。
this和super的区别:
1-this代表本类对象的引用
2-super代表父类存储空间的表示(理解为父类引用,可以操作父类的成员)
怎么使用:
1-调用成员变量
this.成员变量 调用本类的成员变量
super.成员变量 调用父类的成员变量
2-调用构造方法
this(...) 调用本类的构造方法
super(...) 调用父类的构造方法
3-调用成员方法
this.成员方法 调用本类的成员方法
super.成员方法 调用父类的成员方法
继承中构造方法的关系:
子类在实例化对象(不管对象有无参数)的时候会默认先自动调用父类的无参构造方法。(注意:这里的先调用只能理解为先初始化的一个过程。)不然会对程程序执行造成误解!这个一定要注意!
案例:
类Y:
package day08;
public class Y {
public Y(){
System.out.println("Y");
}
}
类X:
package day08;
public class X {
Y y = new Y();
public X(){
System.out.println("X");
}
}
类Z:
package day08;
public class Z extends X {
Y y = new Y();
public Z(){
System.out.println("Z");
}
public static void main(String[] args) {
new Z();
}
}
输出:
Y
X
Y
Z
我们来分析一下结果:首先创建new Z()执行到类Z,Z继承X所以加载到类X中,先执行成员变量Y y = new Y();
加载到类Y中,执行Y的构造方法打印输出Y,然后接着执行X的构造方法打印X,接着执行类Z,执行成员变量Y y = new Y();
打印Y, 最后执行类Z的构造方法打印Z,所以看到结果为YXYZ.记住这是正确的执行过程和结果
对于结果大家可能就有疑惑了,类Z中的构造方法第一句默认有个super()么,那么岂不是执行顺序是最先执行类Z中的Y y = new Y();打印Y
再执行super()依次执行Y y = new Y();打印Y
接着执行类X构造打印X;
然后回到类Z中,super执行完毕,接着执行下一条语句打印Z.
最终结果是YYXZ那么问题就出现了,和控制台的结果是不一样的,说明这种分析是错误的。实际上我们认为的先执行super()没有错误,
关键在于这里的执行只能理解为先去为父类初始化的一个过程。这是问题的关键,并不是程序执行流程。理解这个就知道这是错误,只是先初始化,并非调用执行。
调用父类构造方法可能会使用父类中的数据,所以子类初始化之前一定要先完成父类数据的初始化,不然会造成父亲数据无法访问的情况。
注意:子类的每一个构造方法的第一条默认(不显示但是系统存在)语句都是:super()调用父类的无参构造。
案例:
定义一个父类:
package day08;
public class Fu {
public int num = 100;
public Fu(){
System.out.println("我是父类的构造方法!");
}
}
定义一个子类:
package day08;
public class Zi extends Fu {
public int num = 200;
public Zi(){
System.out.println("我是子类的构造方法!");
}
public void show(){
int num = 300;
System.out.println(num);
System.out.println(this.num);
System.out.println(super.num);
}
}
测试类:
package day08;
public class FuZiMain {
/**
* @param args
*/
public static void main(String[] args) {
//创建子类对象
Zi z = new Zi();
z.show();
}
}
输出结果:
我是父类的构造方法!
我是子类的构造方法!
300
200
100
由结果可以看出,程序首先执行父类的无参构造方法,然后执行子类中的构造方法,接着执行子类中成员方法。
注意事项:如果父类中没有无参构造方法,那么子类的构造方法中会出现什么情况??

解决办法:
1-在父类中加一个无参数的构造方法。
2-子类通过super关键字显示的调用父类的带参构造方法
3-子类通过this调用本类其他构造方法注意:子类构造方法中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。
注意:
1-this或者super()必须出现在第一条语句上。
2-如果不在第一天语句上 就可能对父类进行了多次的初始化,所以必须放在第一条语句。
继承之间成员方法的关系:
1-子类中的方法声明和父类中的方法声明不一样,简单调用不影响。
2-子类中的方法和父类中的方法声明一样时候:
通过子类调用方法
1-先找子类中的方法,看有无这个方法,有就使用
2-再找父类中的方法,看有无这个方法,有就使用
3-如果都没有就报错。
案例:
父类:
package day08;
public class FatherDemo {
public void method(){
System.out.println("我是父类的method方法");
}
public void play(){
System.out.println("我是父类的play方法");
}
}
子类:
package day08;
public class SonDemo extends FatherDemo{
public void show(){
System.out.println("我是子类的show方法");
}
public void method(){
System.out.println("我是子类的method方法");
}
public static void main(String[] args) {
SonDemo sd = new SonDemo();
sd.show();//子类有父类也有,调用子类
sd.method();//子类有父类没有,调用父类
sd.play();//子类没有父类有,调用父类
}
}
输出:
我是子类的show方法
我是子类的method方法
我是父类的play方法