Java学习笔记(八)java继承

前言:

还在学习的过程中

水平有限,不足之处望请斧正。

1、继承的概念

  • 继承是面向对象的三大特征之一
  • 继承可以让类和类之间产生父子关系
  • 继承可以把多个子类中重复的代码抽取到父类中,子类可以直接使用,减少代码的冗余,提高代码复用性

2、继承的格式:

Java 使用extends 关键字来表示继承关系

public static 子类 extends 父类{}

3、继承的特点:

  1. 子类可以得到父类的属性和行为 (不是所有的
  2. 子类可以在父类的基础上增加新的功能
  3. Java只能是单继承:一个子类只能继承一个父类
  4. Java不支持多继承,但是支持多层继承 ( A 可以继承自 B,B可以继承自C )
  5. Java 中所有的类都直接或者间接继承于 Object 类
  6. 子类只能访问父类中非私有的成员

4、什么时候使用继承:

当类和类之间存在共性(相同内容) ,并满足 子类是父类中的一种,就可以考虑使用继承

5、子类可以继承父类哪些内容

父类中包括构造方法,成员变量,成员方法

  • 构造方法:

​ 不论是非私有的还是私有的都无法继承

  • 成员变量:

​ 非私有的可以继承,并且可以使用

​ 私有的可以继承但不能使用

  • 成员方法:

​ 非私有的可以继承,私有的不能继承

关于成员变量的补充:在 java 中为了避免子类调用父类方法时逐层寻找,在最顶级父类中建立了一个虚方法表,用来存储经常可能被用到的方法,并且子类可以得到父类的虚方法表,还可以添加自己的虚方法。( 虚方法表只能用于存储 非private方法,非static 方法,非final方法

6、继承后如何访问成员变量

6.1、成员变量不重名

如果子类和中父类中的成员变量不重名,则访问时没有影响

public class Test {
    public static void main(String[] args) {

       Zi zi = new Zi() ;
       zi.show();

    }
}

class Fu {
    int numFu = 10 ;
}

class Zi extends Fu {
    int numZi = 5 ;

    public void show(){
        System.out.println("父类中的num为: " + numFu);

        System.out.println("子类中的num为: " + numZi);
    }
}

运行结果:
    父类中的num为: 10
	子类中的num为: 5

6.2、成员变量重名

当成员变量重名时,对成员变量的访问遵循就近原则

  • 子类成员变量和父类成员变量重名,在子类中会优先调用子类成员变量
    • 如果此时想要访问父类的成员变量可以通过 super 关键字
  • 成员变量和局部变量重名时,会优先调用局部变量
    • 此时想要访问成员变量可以 使用 this 关键字
  • super代表的是父类对象的引用,this代表的是当前对象的引用。
public class Test {
    public static void main(String[] args) {

        Zi zi = new Zi();
        zi.show();

    }
}

class Fu {
    int num = 10;
}

class Zi extends Fu {
    int num = 5;

    public void show() {
        int num = 1;

        System.out.println("num的值为 " + num);
        System.out.println("this.num 的值为: " + this.num);
        System.out.println("super.num 的值为: " + super.num);

    }
}

运行结果:
    num的值为 1
    this.num 的值为: 5
    super.num 的值为: 10

总结:

​ 继承中成员变量的访问特点:就近原则

​ 默认先在局部位置查找,在本类位置查找,最后在父类位置查找

7、继承后如何访问成员方法

7.1、成员方法不重名

如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。

public class Test {
    public static void main(String[] args) {

        Zi zi = new Zi();
        zi.ziMethod();
        zi.fuMethod();

    }
}

class Fu {
    public void fuMethod() {
        System.out.println("父类中的fuMethod 方法");
    }
}

class Zi extends Fu {
    public void ziMethod() {

        System.out.println("子类中的ziMethod 方法");

    }
}

运行结果:
    子类中的ziMethon 方法
	父类中的fuMethon 方法

7.2、成员方法重名

如果成员方法重名,则创建子类对象调用该方法的时候,子类对象会优先调用自己的方法。

public class Test {
    public static void main(String[] args) {

        Zi zi = new Zi();
        zi.method();

    }
}

class Fu {
    public void method() {
        System.out.println("父类中的method 方法");
    }
}

class Zi extends Fu {
    public void method() {

        System.out.println("子类中的method 方法");

    }
}

运行结果:
    子类中的 method 方法

8、继承中的方法重写

在子类中创建一个与父类中相同名称、相同返回值类型、相同参数列表的方法,只是方法体中的实现不同,以实现不同于父类的功能,这种方式被称为方法重写(override),又称为方法覆盖。当父类中的方法无法满足子类需求或子类具有特有功能的时候,需要方法重写。

重写的要求:

  • 父类的成员方法只能被它的子类重写。

  • 重写方法的名称、形参列表必须与父类中的一致。

  • 子类重写父类方法时,访问权限子类必须大于等于父类 ( 空着 < protected < public )

  • 子类重写父类方法时,返回值类型子类必须小于等于父类

  • 私有方法不能被重写。

  • 子类不能重写父类的静态方法,如果重写会报错的。 ( 只有被添加到虚方法表中的方法才能被重写 )

  • 重写的方法可以使用 @Override 注解来标识。加上注解后如果有红色波浪线,表示语法错误。

public class Test {
    public static void main(String[] args) {

        Zi zi = new Zi();
        zi.method();
        zi.method2();

    }
}

class Fu {
    public void method() {
        System.out.println("父类吃饭");
    }
    public void method2() {
        System.out.println("父亲打儿子");
    }
}

class Zi extends Fu {
    @Override
    public void method() {
        System.out.println("子类吃冰淇凌");

    }
}

运行结果:
    子类吃冰淇凌
	父亲打儿子

9、继承后的构造方法

  • 父类中的构造方法不会被子类继承
  • 子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据,子类初始化之前,一定要调用父类构造方法先完成父类数据空间的初始化。故子类中所有的构造方法默认先访问父类中的无参构造,再执行自己。
  • 子类构造方法的第一行语句默认都是: super(),不写也存在,且必须在第一行。如果想调用父类有参构造,必须手动写super进行调用。
public class Test {
    public static void main(String[] args) {
        Student stu = new Student() ;

        System.out.println("----------------");
        Student stu2 = new Student("张三");
        
    }
}

class Person1{
    private String name ;
    private int age ;
    public Person1(){
        System.out.println("父类的无参构造方法");
    }
}
class Student extends Person1{
    private String schoolName ;

    public Student() {

        //super() ;         //调用父类的无参构造,默认存在可以省略
        System.out.println("子类的无参构造");
    }

    public Student(String schoolName) {
        //super() ;         //调用父类的无参构造,默认存在可以省略
        this.schoolName = schoolName;
        System.out.println("子类的带参构造");
    }
}

运行结果:
    父类的无参构造方法
    子类的无参构造
    ----------------
    父类的无参构造方法
    子类的带参构造

10、super 和 this 关键字的对比

  • this :表示当前方法调用者的地址
  • super :表示父类存储空间
关键字访问成员变量访问成员方法访问构造方法
thisthis.成员变量
访问本类成员变量
this.成员方法
访问本类成员方法
this()
访问本类构方法(一个构造方法调用其它构造方法)
supersuper.成员变量
访问父类成员变量
super.成员方法
访问父类成员方法
super()
访问父类构造方法

今天的分享就到这里了,期待与你共同进步!

如有不足欢迎留言指正 !

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值