【Java SE】继承

本文详细介绍了Java中的继承机制,包括其概念、语法,以及如何在子类中访问父类成员,通过实例展示了super和this关键字的区别,以及final关键字在修饰变量、类和方法时的作用。文章强调了继承在代码复用和面向对象设计中的重要性。
摘要由CSDN通过智能技术生成

🥰🥰🥰来都来了,不妨点个关注叭!
👉博客主页:欢迎各位大佬!👈

在这里插入图片描述

1. 继承

面向对象三大特性:封装、继承、多态
今天我们一起来看看继承这一特性~~~

1.1 继承是什么

Java中使用类对现实世界中实体来进行描述,类实例化后的对象来表示现实中的实体,but现实世界错综复杂,事物之间可能会存在一些关联,对于这些有关联的事物,我们需要合理地设计程序。
比如:狗和猫,它们都是动物,我们可以用Java来描述狗和猫的属性和方法,如下:

public class Dog {
    int legNumber;
    String name;
    String gender;
    int age;
    float weight;

    void eat() {
        System.out.println(name+"在吃饭");
    }

    void sleep() {
        System.out.println(name+"在睡觉");
    }

    void bark() {
        System.out.println(name+"汪汪叫");
    }
}

public class Cat {
    int legNumber;
    String name;
    String gender;
    int age;
    float weight;

    void eat() {
        System.out.println(name+"在吃饭");
    }

    void sleep() {
        System.out.println(name+"在睡觉");
    }

    void meow() {
        System.out.println(name+"喵喵叫");
    }
}

从上述代码中,我们直观清晰看到,狗和猫类中存在大量重复,它们的属性都有腿的数量、名字、性别、年龄、体重和吃饭这个行为,它们的叫声不同。显然,这个代码存在大量重复,是不合理的。
解决办法:面向对象思想中提出了继承的概念,专门用来进行共性抽取,实现代码复用
继承
继承是面向对象最显著的一个特性,继承是从已有的类(父类)派生出新的类(子类),新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
在上述狗和猫的场景中,我们将狗和猫的共性抽取,它们都是动物,很多属性都有共性,我们将这些共性抽取出来,而狗和猫又各自有属于自己的属性,利用继承的思想达到代码共用的思想,动物类则是父类,狗和猫是子类,子类可以复用父类中成员子类在实现时只需关心自己新增加的成员
在这里插入图片描述

1.2 继承的意义

继承有什么意义呢?
继承的意义在于对共性抽取,实现代码复用,是多态性的基础,子类能够更灵活地适应不同的需求,提高代码的通用性和可扩展性,并层次化分类,使程序结构更易于管理。

1.3 继承的语法

在Java中,表示类之间的继承关系,需借助extends关键字,具体语法如下:

class 父类名称 {
// 父类的属性和方法
}
修饰符 class 子类名称 extends 父类名称 {
// 子类特有的属性和方法
// 子类可以覆盖父类的方法
}

通过上述的分析,使用继承的思想重新设计,各部分代码如下:

public class Animal {
    int legNumber;
    String name;
    String gender;
    int age;
    float weight;

    void eat() {
        System.out.println(name+"在吃饭");
    }

    void sleep() {
        System.out.println(name+"在睡觉");
    }
}
public class Dog extends Animal{
    void bark() {
        System.out.println(name+"汪汪叫");
    }
}
public class Cat extends Animal {
    void meow() {
        System.out.println(name+"喵喵叫");
    }
}
public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();
        dog.name = "球球";
        cat.name = "毛毛";
        dog.bark();
        cat.meow();
    }
}

【注意事项】
1)一个.java文件写一个类,如下写法:
在这里插入图片描述
2)Dog类和Cat并没有定义成员变量,name是从父类Animal继承过来的,eat()和sleep()方法也是继承来的,即子类会将父类中的成员变量或者成员方法继承到子类中
3) 子类继承父类后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承,完全可以直接用父类呀~所以,必须要新添加自己特有的成员

1.4 继承的方式

在现实世界中,事物之间的关系是十分复杂的~那Java支持哪些继承方式呢!
在这里插入图片描述
Java支持单继承、多层继承、不同类继承同一类
不支持多继承(一个子类继承多个父类,不支持)!!!
在这里插入图片描述
Java中不支持多继承
尽管在写代码时候,我们可能会碰到类之间有非常复杂的关系,但是仍然不希望类之间的继承关系超过三层, 继承层次太多, 需要考虑对代码进行重构
如果想从语法上进行限制继承,使用 final 关键字修饰类,表示该类不可以被继承

1.5 子类中访问父类成员

1.5.1 子类中访问父类成员变量

【子类和父类不存在同名成员变量】

public class Parent {
    String a;
    String b;
}
public class Child extends Parent{
    String c;
    public void method() {
        a = "我是父类的a";
        b = "我是父类的b";
        c = "我是子类特有的c";
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }
}
public class Test {
    public static void main(String[] args) {
        Child child = new Child();
        child.method();
    }
}

运行结果如图:
在这里插入图片描述
解释:子类中没有a和b变量,a、b访问从父类Parent类继承下来的a、b,子类中有变量c,c是访问子类自己的c
【子类和父类存在同名成员变量】

public class Parent {
    String a;
    String b;
    String c;
}
public class Child extends Parent{
   String a;
   char b;

    public void method() {
        a = "我是子类Child类中的a";
        b = 'b';
        c = "我是父类Parent类中的c";
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }
}
public class Test {
    public static void main(String[] args) {
        Child child = new Child();
        child.method();
    }
}

运行结果如图:
在这里插入图片描述
解释:子类中有变量a则访问的是自己的a,而变量b在父类与子类中均有,类型不同,可以看到,优先访问的是子类中的变量b,子类中没有变量c则访问从父类继承下来的c
总结
通过子类对象或者在子类方法中访问成员时,以下3种情况:
(1) 访问的成员变量子类中有,优先访问自己的成员变量
(2) 访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错
(3) 访问的成员变量与父类中成员变量同名,则优先访问自己的
即成员变量访问遵循就近原则,自己有则优先访问自己的,否则在父类中寻找

1.5.2 子类中访问父类成员方法

【子类和父类不存在同名成员方法】

public class Parent {
    public void methodA() {
        System.out.print("父类Parent类中的methodA()方法!");
    }
}
public class Child extends Parent{
    public void methodB() {
        System.out.print("子类Child类中的methodB()方法!");
    }

    public void methodC() {
        methodA();
        methodB();
    }
}
public class Test {
    public static void main(String[] args) {
        Child child = new Child();
        child.methodC();
    }
}

运行结果如图:
在这里插入图片描述
解释:子类中没有methodA()方法,子类访问父类Parent类继承下来的methodA()方法,methodB()方法是访问子类自己的methodB()方法
【子类和父类存在同名成员方法】

public class Child extends Parent{
    public void methodA(int a) {
        System.out.println("Child子类中的methodA(int)方法");
    }

    public void methodB() {
        System.out.println("子类Child类中的methodB()方法!");
    }

    public void methodC() {
        methodA();
        methodA(12);
        methodB();
    }
}

public class Parent {
    public void methodA() {
        System.out.println("父类Parent类中的methodA()方法!");
    }
    public void methodB() {
        System.out.println("父类Parent类中的methodB()方法!");
    }
}
public class Test {
    public static void main(String[] args) {
        Child child = new Child();
        child.methodC();
    }
}

运行结果如图:
在这里插入图片描述
解释:子类中的methodA()和父类中的methodA()构成重载,根据调用方法,调用哪个就是哪个,methodA()未传参,调用父类的,methodA(12)传参了,调用子类Child的methodA(12)方法。methodB同名,调用子类自己的methodB()方法
总结
(1) 子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问父类的,否则编译报错
(2) 子类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果参数列表一致,优先在子类中找访问自己的
即成员方法访问遵循就近原则,自己有则优先访问自己的,否则在父类中寻找,如果方法重载,根据调用方法选择一致的

1.6 super关键字

我们知道,如果子类自己有变量c,那么优先访问子类的c,如果我想访问父类的c,该如何做捏!
在这里插入图片描述
此时super关键字,闪亮登场!!!
Java提供super关键字,该关键字主要作用就是在子类方法中访问父类的成员

public class Parent {
    String a  = "我是父类Parent类中的a";
    String b  = "我是父类Parent类中的b";
    String c;
    public void methodA() {
        System.out.println("我是父类Parent类中的methodA()");
    }
}

public class Child extends Parent{
   String a = "我是子类Child类中的a";
   char b;

   public void methodA() {
       System.out.println("我是子类Child类中的methodA()");
   }
    public void method() {
        System.out.println(a);//a相当于this.a
        System.out.println(super.a);
        methodA();//methodA()相当于this.methodA()
        super.methodA();
    }
}
public class Test {
    public static void main(String[] args) {
        Child child = new Child();
        child.method();
    }
}

运行结果如下:
在这里插入图片描述

优先访问子类中的成员,无法访问到父类中的成员,通过关键字super可以访问到父类的成员变量和方法
注意事项
(1) 只能在非静态方法中使用
(2) 在子类方法中,访问父类的成员变量和方法

1.7 子类构造方法

父子,即先有父再有子,在子类构造方法内,必须先帮助父类构造
在子类构造方法中,虽然并没有写任何关于父类的构造的代码,通过代码运行结果得知,在构造子类对象时,先执行父类的构造方法,后执行子类的构造方法

public class Parent {
    public Parent() {
        System.out.println("父类Parent构造方法");
    }
}

public class Child extends Parent{
   public Child() {
//super(); 被隐藏了 
//子类构造方法中默认会调用父类的无参构造方法super()
//没有写时,编译器会自动添加,且super()必须是子类构造方法中第一条语句,
//且只能出现一次
       System.out.println("子类Child构造方法");
   }
}
public class Test {
    public static void main(String[] args) {
        Child child = new Child();
    }
}

运行结果如下:
在这里插入图片描述
原因】子类对象中成员由两部分组成,父类继承下来的+子类新增加的部分,先有父再有子,所以在构造子类对象时候 ,先要调用父类的构造方法,将从父类继承下来的成员构造完整,再调用子类自己的构造方法,将子类自己新增加的成员初始化完整
在这里插入图片描述

注意事项
(1) 父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用父类构造方法

public Parent() {
}

public Child() {
    super(); 
}

(2) 父类构造方法是带有参数的,此时需要为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败,即子类必须先帮助父类构造

public class Parent {
    String name;
    int age;
    public Parent(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
public class Child extends Parent{
     int index;
     public Child(String name, int age,int index) {
       super(name,age); //必须先帮助父类构造且super为第一条语句,交换顺序则会报错,且super只出现一次!
       this.index = index;
   }
}

(3) 在子类构造方法中,super(…)调用父类构造时,必须是子类构造函数中第一条语句,且只能出现一次并且不能和this同时出现!!!即this和super调用构造器不能同时出现

public class Child extends Parent{
    int index;
   public Child(String name, int age,int index) {
       super(name,age);
       this("1",2,4);//将会报错!!不能同时出现
   }
}

2. super与this关键字

相同点
(1) 均为Java中的关键字
(2) 均只能在类的非静态方法中使用,用来访问非静态成员方法和变量
(3) 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
不同点
(1) this是当前对象的引用,当前对象即调用实例方法的对象,super是子类对象中从父类继承下来部分成
员的引用

(2) 在非静态成员方法中,this访问本类的方法和属性super访问父类继承下来的方法和属性
(3) 在构造方法中:this(…)调用本类构造方法super(…)调用父类构造方法,两种调用不能同时在构造方法中出现
(4) 构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有

3. final 关键字

final关键字可以用来修饰变量、成员方法以及类

3.1 修饰变量或字段

表示该变量不能被修改(即常量)

final int a = 100;
a = 20;
//编译出错,变量a被final修饰,不能被修改

3.2 修饰类

表示该类不能被继承

final public class Animal {
	...
}

public class Cat extends Animal{
	...
}
//编译出错,Animal类被final关键字修饰,表示不能被继承

3.3 修饰方法

表示该方法不能被重写

本期内容到这里结束啦~以下为本期内容回顾!
在这里插入图片描述下期再见啦~

  • 33
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值