Day08
继承
继承父类之后,不需要写父类的代码,就能引用父类的方法、访问父类的属性
extends关键字
[!IMPORTANT]
继承extends父类之后不一定需要重写父类方法,分两种情况:
- 当父类方法为抽象方法时,子类必须重写所有父类抽象方法,或者子类的子类中实现也可
- 当父类方法为普通方法时,子类可以重写父类方法,也可不重写
实现implements接口时,需要重写(实现)接口中所有方法
作用:实现代码复用
规则:
-
子类可以访问子类和父类
-
父类不能访问子类
-
单一继承:一个父类可以有多个子类,但一个子类只能有一个父类
-
继承传递:子类可以成为其他类的父类,称为子类的子类,即继承的传递,且子类的子类既可以访问其父类,也可以访问其父类的父类
-
继承的是父类的成员变量和普通方法,不包括构造方法,子类要访问父类构造方法需要使用super关键词进行访问
-
继承后父类和子类本质上是一个类,所以子类中添加了和父类方法名字相同、参数列表不同的方法时,该方法重载
Class Person{ say(){ ... } } Class Student extends Person{ say(String a){ //重载方法 ... } }
super关键词
作用:指代当前对象的超类对象(父类对象)
常见使用场景:
-
访问父类的成员变量
class Person{ String name; int age; } class Student extends Person{ String studentId; Student(String name, int age, String studentId){ supper.name = name;//也可以写成this.name = name; supper.age = age;//同上 this.studentId = studentId; } }
特殊情况:子类与父类有同名的属性,在子类中访问时this和super作用不可互通,要访问父类的属性只能用super,要访问本类只能用this
class Person{ String name; int age; int b; } class Student extends Person{ String studentId; int b; Student(String name, int age, String studentId, int b){ supper.name = name;//也可以写成this.name = name; supper.age = age;//同上 this.studentId = studentId; this.b = b;//访问的是本类的b super.b = b;//访问的是父类的b } }
-
调用父类的方法
super.父类方法名;
-
调用父类的构造方法
-
无参
-
当继承完成后,子类会自动默认生成一个super()无参方法,用于调用父类中默认生成的无参构造方法,若父类中的无参构造已经被有参构造覆盖,则子类无参构造会报错,因为其中自动生成的super()方法已失效,此时只能自己调用有参super构造
Student(){ super();//默认生成,不显式展示 }
-
子类中若自己调用了父类的构造方法,则不再默认提供super方法
-
-
有参
public Student(String name, int age, String adress, String className, String studentId) { super(name, age, adress);//调用父类有参构造 this.className = className; this.studentId = studentId; }
-
方法的重写
发生于子父类中,子类重写父类的方法,名称相同、参数列表相同,只是内部逻辑不同
-
重写方法被调用时,看调用对象是谁执行的就是谁的方法
Student stu = new Student(); stu.sayHi();//Student重写了sayHi()方法,调用Student类中的sayHi()方法 Doctor doctor = new Doctor(); doctor.sayHi();//Doctor类没有重写sayHi,所以此处还是调用Person类中的方法
-
子类在重写父类方法后,可以在重写的方法内通过super关键字重新调用父类的被重写方法执行
class Person{ String name; int age; sayHi(){ ... } } class Student extends Person{ String studentId; sayHi(){ ... super.sayHi();//调用父类sayHi()方法 } }
重写和重载的区别
重写 | 重载 |
---|---|
发生在子类父类之间,是垂直关系 | 发生在本类之内,是水平关系 |
方法名、参数列表均不变 | 方法名不变,参数列表必须改变 |
返回类型必须与被重写方法相同 | 返回类型可以不同 |
访问修饰符限制一定要大于被重写方法的访问修饰符 | 可以有不同的访问修饰符,没有大小限制 |
重写方法一定不能抛出新的异常或者比被重写方法更宽泛的异常 | 可以抛出不同的异常 |
访问修饰符的范围:
public | protected | default | private | |
---|---|---|---|---|
同类 | √ | √ | √ | √ |
同包 | √ | √ | √ | |
不同包子类 | √ | √ | ||
不同包其他类 | √ |
final关键字
不可改变
特点:
- 修饰变量:该变量自定义并初始化之后便不能修改
- 修饰方法:该方法不可被重写
- 修饰类:该类不能被继承
优势:
- 提高性能,JVM会在常量池中缓存final变量
- final变量在多线程中并发安全,无需额外的同步开销
- final时静态编译的,调用速度提高
- final类创建的对象是只可读的,多线程中可以安全共享