面向对象的三大特征:封装、继承、多态
一、继承
Java中提供了一个关键字extend,通过这个关键字,我们可以使得一个类与另一个类建立联系
e.g:
public class Student extend Person(){
}
二、继承的好处
1、可以将子类中重复的代码抽取到父类中,提高代码的复用性
2、子类可以在父类的基础上增加功能,使子类更强大
三、什么时候用继承
当类与类之间存在相同的内容,并满足子类是父类中的一种,就可以使用继承来优化代码
四、继承的特点
Java只支持单继承,不支持多继承,但支持多层继承
单继承:一个子类只继承一个父类
多层继承:子类A可以继承父类B,父类B可以继承其父类C,其中父类B是子类A的直接父类,父类C是子类A的间接父类
Java的每个类都直接或间接地继承Object类
e.g:
public class Student (){
}
虽然该类没有写extend xxx 但是它也是有继承的类,即Object
五、继承的注意事项
如果父类的成员变量和成员方法被private修饰时 子类就无法调用父类的成员变量和成员方法了 private只能在本类中被访问 子类只能访问父类的非私有的成员
六、子类能继承父类的哪些东西
父类的成员包括构造方法、成员变量、成员方法
构造方法、成员变量、成员方法的修饰符大概分为两大类:私有(private)、非私有(public...)
1、父类的构造方法无论是私有的还是非私有的都不可以被子类继承
因为构造方法的名称必须与类名一致,而子类和父类的名称不一样,所以子类不能继承父类的构造方法
2、父类的成员变量无论是私有的还是非私有的都可以被子类继承,但是不能被子类调用
3、父类的成员方法私有的不可以子类继承,非私有的都可以子类继承(继承的是虚方法表,虚方法表由父类中非private、非static、非final的方法构成)
七、继承中方法的重写
1、重写的概念
当父类的方法不满足子类现在的需求时,需要进行方法的重写
2、书写格式
在继承体系中,子类出现和父类一模一样的方法声明时,我们称这个方法是重写的方法
3、重写注解
@Override是放在重写的方法上,校验子类重写时语法是否正确
加上注解后如果有红色波浪线,表示语法错误,需要修改你重写的方法
建议重写方法都加@Override注解,代码安全
4、方法重写的本质
方法重写的本质是覆盖虚方法中的方法,因为子类继承的方法是父类的虚方法表
5、方法重写的注意事项
1、重写的方法名称、形参列表必须与父类一致
2、子类重写父类方法时,访问权限子类必须大于父类 权限的范围大小排序:(空着不写<protected<pubilc)
3、子类重写父类方法时,返回值类型子类必须小于父类(了解)
4、只有被添加到虚方法中的方法才能被重写
5、子类的方法尽量与父类的方法保持一致
八、继承中成员的访问特点
1、继承中成员变量的访问特点
满足就近原则,谁离我近,我就用谁
先找局部变量,如果找不到,再找成员变量,没有找到,最后再父类中找,还是找不到就会报错
当我们想使用子类的成员变量或者父类的成员变量时,我们可以使用this、super来指代,super指的是父类,当用this修饰时,就会直接在子类的成员变量中找,如果找不到,则会在父类的成员变量中找
public class test1 {
public static void main(String[] args) {
Son s=new Son();
s.show();
}
}
class Daddy {
String name = "Daddy";
int age;
public Daddy() {
}
}
class Son extends Daddy{
String name="Son";
public void show(){
String name="儿子";
System.out.println(name); // 就近原则
System.out.println(this.name); // this代表对象的成员变量
System.out.println(super.name); // super代表父类的成员变量
}// 输出:
// 儿子
// Son
// Daddy
}
注意:在子类中自能调用一个super,调用多个super会报错
public class test1 {
public static void main(String[] args) {
Son s=new Son();
s.show();
}
}
class Daddy {
String name = "Daddy";
int age=20;
public Daddy() {
}
}
class Son extends Daddy{
String name="Son";
public void show(){
String name="儿子";
// 1、打印"儿子"
System.out.println(name); // 就近原则
// 2、打印"20"
// 有三种方式
System.out.println(age); // 就近原则 局部没有,子类的成员变量没有,就找父类的成员变量
System.out.println(this.age); // this会在子类的成员变量中找 找不到就在父类的成员变量找
System.out.println(super.age); // super代表父类的成员变量
// 3、打印"Daddy"
System.out.println(super.name);
}
}
2、继承中成员方法的访问特点
直接访问,满足就近原则,谁离我近,我就用谁,使用super访问父类
通俗来讲,就是在本类中查看是否有该方法,如果没有该方法则调用从父类中继承下来的方法
package day_1;
public class test1 {
public static void main(String[] args) {
Son s=new Son();
s.lunch();
}
}
class Daddy {
public void eat(){
System.out.println("吃饭");
}
public void drink(){
System.out.println("喝水");
}
}
class Son extends Daddy{
public void lunch(){
eat(); // 当方法没有任何修饰时,采用就近原则,离谁近就用谁,这里eat、drink方法离Daddy父类近
drink();
System.out.println("-----------------------------");
this.eat(); // this会在先子类的方法中找 找不到就在父类的方法变量找
this.drink();
System.out.println("-----------------------------");
super.eat(); // super是调用父类的成员方法
super.drink();
}
}
// 输出结果:
// 吃饭
// 喝水
// -----------------------------
// 吃饭
// 喝水
// -----------------------------
// 吃饭
// 喝水
public class test1 {
public static void main(String[] args) {
Son s=new Son();
s.lunch();
}
}
class Daddy {
public void eat(){
System.out.println("吃饭");
}
public void drink(){
System.out.println("喝水");
}
}
class Son extends Daddy{
public void eat(){
System.out.println("嗦粉");
}
public void drink(){
System.out.println("喝饮料");
}
public void lunch(){
eat(); // 当方法没有任何修饰时,采用就近原则,离谁近就用谁,这里eat、drink方法离Son子类近
drink();
System.out.println("-----------------------------");
this.eat(); // this会在先子类的方法中找 子类有eat、drink方法就调用子类
this.drink();
System.out.println("-----------------------------");
super.eat(); // super是调用父类的成员方法
super.drink();
}//
// 嗦粉
//喝饮料
//-----------------------------
//嗦粉
//喝饮料
//-----------------------------
//吃饭
//喝水
}
3、继承中构造方法的访问特点
1、父类中的构造方法不会被子类继承
2、子类中的构造方法默认先访问父类的无参构造,再执行自己的构造方法
因为子类在初始化的时候,有可能使用到父类的数据,如果父类没有初始化,则子类无法使用到父类的数据,因此子类再初始化之前,一定要调用父类的构造方法完成父类数据空间的初始化
如何调用父类的构造方法:
1、子类构造方法(无论是空参构造还是有参构造)的第一行语句默认是:super(),不写也是存在,且必须在第一行,这里的super()默认调用的是父类的无参构造
2、如果父类没有无参的构造方法,但父类有有参的构造方法,需要在子类的构造方法中主动调用父类有参数的构造方法
3、如果想调用父类的有参构造,必须手动写super进行调用
4、父类的有参构造必须由子类的有参构造方法调用,子类的无参调用只能调用父类的无参构造