继承
继承是多态的前提,没有继承就没有多态
继承主要解决的问题就是:共性抽取
父类与子类:把公共的东西抽取到一起
特点:
- 子类可以拥有父类的“内容”
- 子类还可以拥有自己专属的内容
在继承的关系中,“子类就是父类”。也就是说,子类可以当作父类看待
- 列如:父类是员工,子类是讲师,那么“讲师就是员工”
- 定义父类的格式:(一个普通的定义类)
- public class 父类名称{
-
//...
- }
- 定义子类的格式:
- public class 子类名称 extends 父类名称{
-
//
- }
例:
// 定义一个父类:员工
public class Employee {
public void method(){
System.out.println("方法执行");
}
}
//定义了一个员工的子类:讲师
public class Teacher extends Employee{
}
public class Demo01Extends {
public static void main(String[] args) {
//创建了一个子类对象
Teacher teacher = new Teacher();
//Teacher类当中虽然什么都没写,但是会继承来自父类的method方法
teacher.method();
在父子类的继承关系中,如果成员变量重名,则创建子类对象时,访问有两种方式:
- 直接通过子类对象访问成员变量: 等号左边是谁就用谁,没有则向上找。
- 间接通过成员方法访问成员变量: 该方法属于谁,就优先用谁,没有则向上找
例:
public class Fu {
int numFu = 10;
int num = 100;
public void methodFu(){
System.out.println(num); //使用的是本类当中的,不会向下找子类
}
}
public class Zi extends Fu{
int numZi = 20;
int num = 200;
public void methodZi(){
//因为本类当中有num,所以这里用本类当中的num
System.out.println(num);
}
}
public static void main(String[] args) {
Fu fu = new Fu();
System.out.println(fu.numFu);
Zi zi = new Zi();
System.out.println(zi.numFu);//10
System.out.println(zi.numZi);//20
//等号左边是谁,就优先用谁
System.out.println(zi.num); //优先子类:200
//System.out.println(zi.abc); //若都没有则编译报错
System.out.println("===========");
//这个方法是子类的,优先用子类的,没有再向上找
zi.methodZi(); //200
//这个方法是在父类当中定义的,
zi.methodFu();//100
}
- 在父子类的继承关系中,创建子类对象,访问成员方法的规则:
创建的对象是谁,就优先用谁,如果没有就向上找 - 注意事项:
- 无论是成员方法还是成员变量,如果没有都向上找父类,绝不会向下找子类的
例:
public static void main(String[] args) {
Zi zi = new Zi();
zi.methodZi(); //子类方法执行
zi.methodFu();//父类方法执行
zi.method();//子类重名方法执行
//因为创建了子类对象,所以优先子类方法
}
}
public class Fu {
public void methodFu(){
System.out.println("父类方法执行");
}
public void method(){
System.out.println("父类重名方法执行");
}
public class Zi extends Fu {
public void methodZi(){
System.out.println("子类方法执行");
}
public void method(){
System.out.println("子类重名方法执行");
}
重写(Override):
-
概念:在继承关系中,方法名称一样,参数列表也一样。
-
重写(Override):
-
概念:方法名称一样,参数列表也一样。 覆盖,复写。
-
重载(OverLoad):
-
概念:方法的名称一样,参数列表不同
-
方法的覆盖重新特点:创建的是子类对象,则优先用子类方法
-
方法覆盖重写的注意事项:
-
1 必须保证父子类之间方法的名称相同,参数列表也相同。
-
@Override: 写在方法前面,用来检测是不是有效的正确覆盖重写。
-
这个注解就算不写,只要满足要求,也是正确的方法覆盖重写
-
2 子类方法的返回值必须[小于等于父类]方法的返回值范围
-
Object类是所有类的公共最高父类,java.lang.String就是Object的子类。
-
3 子类方法的权限必须大于等于父类方法的权限修饰符
-
小扩展提示:public > protected > (default) > private
-
备注:(default)不是关键字default,而是什么都不写,留空
例题:
注意:把父类当中的方法拿到子类当中用,使用super方法
public static void main(String[] args) {
Phone phone = new Phone();
phone.call(); //打电话
phone.send(); //发短信
phone.show(); //显示号码
System.out.println("========");
NewPhone newPhone = new NewPhone();
newPhone.show(); //显示号码 显示姓名 显示头像
newPhone.call(); //打电话
newPhone.send(); //发短信
}
public class Phone {
public void call(){
System.out.println("打电话");
}
public void send(){
System.out.println("发短信");
}
public void show(){
System.out.println("显示号码");
}
public class NewPhone extends Phone{
@Override
public void show() {
super.show(); //把父类的show方法拿来重复利用
System.out.println("显示姓名");
System.out.println("显示头像");
}
}
继承关系中,父子类构造方法的访问特点:
-
1 子类构造方法当中有一个默认隐含的“super()调用”,所以一定是先调用父类构造,后执行的子类构造。
-
2 子类构造可以通过super关键字来调用父类重载构造
-
3 super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造
-
4 子类必须调用父类构造方法,不写则赠送super(); 写了则用写的指定的super调用,super只能有一个,还必须是第一个*
例:
public static void main(String[] args) {
Zi zi = new Zi();
}
public class Fu {
public Fu(){`在这里插入代码片`
System.out.println("父类无参构造");
}
public Fu(int num){
System.out.println("父类有参构造");
}
public class Zi extends Fu {
public Zi(){
//super(); //在调用父类的无参构造
super(20); //调用父类重载的构造方法
System.out.println("子类构造方法");
}
public void method(){
//super(); 错误写法,只有子类构造方法,才能调用父类构造方法。
}
如上面的代码,若Zi类当中再写一个super语句,则是错误的。
Super关键字:
-
super 关键字的用法有三种:
-
1 在子类的成员方法中,访问父类的成员变量
-
2 在子类的成员方法中,访问父类的成员方法
-
3 在子类的构造方法中,访问父类的构造方法
public class Fu {
int num = 10;
public void method(){
System.out.println("父类方法");
}
public class Zi extends Fu {
int num = 20;
public Zi(){
super(); //不写也有
}
public void methodZi(){
System.out.println( super.num); //父类中的num
}
public void method (){
super.method(); //访问父类当中的method
System.out.println("子类方法");
}
this关键字:
-
super关键字用来访问父类内容,而this关键字用来访问本类内容,用发也有三种:
-
1 在本类的成员方法中,访问本类的成员变量
-
2 在本类的成员方法中,访问本类的另一个成员方法
-
3 在本类的构造方法中,访问本类的另一个构造方法
在第三种用法当中要注意:
A:this(…)调用也必须是构造方法的第一个语句
B:super和this两种构造调用,不能同时使用。
int num = 20;
public Zi(){
// super(); //这一行不再赠送
this (123); //本类的无参构造,调用本类的有参构造
// this(1,3) //错误写法
}
public Zi(int n ){
this(1,3);
}
public Zi(int n, int num){
}
public void showNum(){
int num = 10;
System.out.println(num); //局部变量
System.out.println(this.num); //本类中的成员变量
System.out.println(super.num);//父类中的成员变量
}
public void methodA(){
System.out.println("AAA");
}
public void methodB(){
this.methodA(); //访问了A的方法
System.out.println("BBB");
}
Java语言是单继承的
一个类的直接父类只有一个
例:
class A{}
class A{}
class D extends A,C{} //错误写法
Java语言可以多级继承。
class A{}
class B extends A {}// 正确
class C extends B {} //正确
最高父类:java.lang.Object
一个子类的父类是唯一的,但是一个父类可以拥有很多个子类
class A{}
class B extends A {} //正确
class C extends A {} //正确