继承可以解决代码的复用,让我们的编程更加靠近人类思维,当多个类存在相同的属性和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends语句来声明继承。
注意事项
Ⅰ.java 中支持单继承,不直接支持多继承,但对c++中的多继承机制进行改良。
Ⅱ.ava支持多层(多重)继承
Ⅲ.Java所有类都是Object类的子类
Ⅳ.JDK中有202个包3777个类、接口、异常、枚举、注释和错误
实例
1 packagecom.beekc.www;2
3 public classBeekc {4 public static voidmain(String[] args) {5 Pupil stu1 = newPupil();6 stu1.pay(500);7 stu1.printName();8 stu1.printFee();9
10 MiddleStu stu2 = newMiddleStu();11 stu2.pay(500);12 stu2.printName();13 stu2.printFee();14
15 ColStu stu3 = newColStu();16 stu3.pay(500);17 stu3.printName();18 stu3.printFee();19 }20 }21
22 //将学生的共有属性提出,做一个父类
23 classStu24 {25 protected intage;26 publicString name;27 public floatfee;28 //编程中,如果你不希望子类继承某个属性或者方法29 //将其声明为private
30 privateString job;31
32 public voidprintName()33 {34 System.out.printf("名字:" + this.name + "\t");35 }36 public voidprintFee()37 {38 System.out.println("交费" + this.fee + "¥");39 }40 }41
42 //小学生类
43 class Pupil extendsStu44 {45 publicPupil()46 {47 name = "小学生";48 }49 //交费
50 public void pay(floatfee)51 {52 this.fee =fee;53 }54 }55
56 //中学生类
57 class MiddleStu extendsStu58 {59 publicMiddleStu()60 {61 name = "中学生";62 }63 //交费
64 public void pay(floatfee)65 {66 this.fee = fee * 0.8f;67 }68 }69
70 //大学生类
71 class ColStu extendsStu72 {73 publicColStu()74 {75 name = "大学生";76 }77 //交费
78 public void pay(floatfee)79 {80 this.fee = fee * 0.6f;81 }82 }
运行结果
继承的细节
1 //第一种情况:当子类与父类的变量的名称相同时,在子类里想用父类的变量时用super关键字
2 public classFather {3 int num = 4;4 }5
6 public classSon extends Father {7 int num = 5;8 public voidshow()9 {10 System.out.println(this.num + "..." +super.num);11 }12 }13
14 public classExtendsDemo {15 public static voidmain(String[] args)16 {17 Son son = newSon();18 son.show();19
20 }21 }
1 //第二种情况:当父类的方法与子类的方法想同时,子类的方法会去覆盖父类的方法,这里会去输出子的内容,想要用父类的方法用super关键字
2 public classFather {3 public voidshow()4 {5 System.out.println("Father run ...");6 }7 }8
9 public class Son extendsFather {10 public voidshow()11 {12 System.out.println("Son run ...");13 }14 }15
16 public classExtendsDemo {17 public static voidmain(String[] args)18 {19 newSon().show();20 }21 }
1 //第三种情况:子类方法覆盖父类方法时,子类权限必须要大于等于父类的权限2 //这个程序会报错
3 public classFather {4 public void show() //这里权限是public
5 {6 System.out.println("Father run ...");7 }8 }9
10 public class Son extendsFather {11 private void show()//这里权限是private
12 {13 System.out.println("Son run ...");14 }15 }16
17 public classExtendsDemo {18 public static voidmain(String[] args)19 {20 newSon().show();21 }22 }
//会报错的程序:静态方法只能覆盖静态方法,或被静态覆盖
class Father
{
public static void show()
{
System.out.println("run show");
}
}
class Son extends Father
{
public void show()
{
System.out.println("run show");
}
}
class ExtendsDome
{
public static void main(String[] args)
{
Son son = new Son();
son.show();
}
}
1 //第四种情况:会报错的程序:静态方法只能覆盖静态方法,或被静态覆盖
2 classFather3 {4 public static voidshow()5 {6 System.out.println("run show");7 }8 }9
10 class Son extendsFather11 {12 public voidshow()13 {14 System.out.println("run show");15 }16 }17
18 classExtendsDome19 {20 public static voidmain(String[] args)21 {22 Son son = newSon();23 son.show();24 }25 }
什么时候使用覆盖操作?
当对一个类进行子类的扩展时,子类需要保留父类的功能声明。但是要定义子类中该功能的特有内容时,就使用覆盖操作完成。
子父类中的构造函数的特点
在子类构造对象时,发现,访问子类构造函数时,父类也运行。为什么呢?原因是:在子类的构造函数中第一行有一个默认的隐式语句。super();
子类的实例化过程,子类中的构造函数默认都会访问父类中的空参数构造函数.
1 classFather2 {3 Father()4 {5 System.out.println("Father run");6 }7 }8
9 class Son extendsFather10 {11 Son()12 {13 //super();//隐藏的语句,此语句是调用父类的空参数构造函数
14 System.out.println("Son run");15 //return;
16 }17 }18
19 classExtendsDome20 {21 public static voidmain(String[] args)22 {23 newSon();24 }25 }26
27 //运行结果28 //Father run29 //Son run
为什么子类实例化的时候要访问父类的构造函数呢?
那是因为子类继承了父类,获取到了父类的内容(属性),所以在使用父亲内容之前,要先看父类如何对自己的内容进行初始化的。所以子类在构造对象时,必须访问父类中的构造函数。为什么完成这个必须的动作,就在子类的构造函数中加入了super()语句。 如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确要掉调用父类中哪个构造函数.同时子类构造函数中如果使用this调用了本类构造函数时,那么super就没有被替换了,因为super和this只能定义在第一行,所以只能有一个。但是可以保证的是,子类中肯定会有其他的构造函数访问父类的构造函数。注意的是super语句必须要定义在子类构造函数的第一行,因为父类的初始化动作要先完成。
1 classFather2 {3 Father()4 {5 System.out.println("Father run");6 }7 Father(intx)8 {9 System.out.println("Father run ..." +x);10 }11 }12
13 class Son extendsFather14 {15 Son()16 {17 //super();//这里回去初始化父类的构造函数
18 System.out.println("Son run");19 return;20 }21 Son(intx)22 {23 this();24 //super();//这里的super()会被替换,因为this()与super()只能写在第一行。
25 System.out.println("Son run ..." +x);26 return;27 }28 }29
30 classExtendsDome31 {32 public static voidmain(Sring[] args)33 {34 new Son(6);35 }36 }37
38 //运行结果39 //Father run40 //Son run41 //Son run ...6
1 classFather2 {3 Father()4 {5 super();6 show();7 return;8 }9
10 public voidshow()11 {12 System.out.println("Father show");13 }14 }15
16 class Son extendsFather17 {18 int num = 8;19
20 Son()21 {22 super();23 //通过super初始化父类时,子类的成员变量并未显示初始化。等super()父类初始化完毕后,才进行子类的成员变量显示初始化。
24 show();25 return;26 }27 public voidshow()28 {29 System.out.println("Son show ..." +num);30 }31 }32
33 classExtendsDome34 {35 public staticviod main(String[] args)36 {37 Son son = newSon();38 son.show();39 }40 }41
42 //运行结果43 //Son show ...044 //Son show ...8