Java -继承(超超超详细)

继承

I、继承的概念

在Java中,我们会学到一个有一点抽象但是十分重要的概念叫做继承。一提起继承,大家会想到什么?裹着白头巾小小年纪就失去烦恼的卡塔尔王储?还是支付宝里花呗的继承。
在这里插入图片描述
太惨了,真可怜。小小年纪就失去了烦恼和奋斗的动力。
咱们扯回正题为什么Java需要继承?我们先来看看继承到底是个啥子:

Java中使用类对现实世界中实体来进行描述,类经过实例化之后的产物对象,则可以用来表示现实中的实体,但是
现实世界错综复杂,事物之间可能会存在一些关联,那在设计程序是就需要考虑

看起来感觉确实是说了,但又没完全说。。。。。我们还是通过代码来简单明了的说明吧

II、代码演示说明

class Animal {
    public String name;
    public int age;
    public int a = 199;
    public void Eat() {
        System.out.println(name+ "正在吃饭");
    }
}
class Dog extends Animal {
    public int a = 122;
    public void Wangwang() {
        System.out.println(name+"汪汪叫");
        System.out.println(super.a);
    }
}
public class InheritTest {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "Xiamu";
        dog.age = 3;
        dog.Eat();
        dog.Wangwang();
    }
}

在这个代码中,我们一步一步来分析。首先我们大致浏览了一下,我们定义了两个类,一个是animal类,还有一个是Dog类。一目了然。动物我们都知道是一个大类,狗隶属于这个大类里面,那么,动物有的,比如说吃饭,睡觉,狗一定有。我们在定义其他类例如猫的时候,如果没有animal这个大类,我们需要再写一个方法,因而,继承这时候就显得特别重要了。
这里,画个图在自然就能明了:
在这里插入图片描述

III、语法相关

、在Java中如果要表示类之间的继承关系,需要借助extends关键字。其次,我们有两个需要注意的地方:

  1. 子类会将父类中的成员变量或者成员方法继承到子类中了
  2. 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了

、子类和父类成员变量同名的情况:

public class Base {
int a;
int b;
int c;
}
public class Derived extends Base{
int a; // 与父类中成员a同名,且类型相同
char b; // 与父类中成员b同名,但类型不同
public void method(){
a = 100; // 访问父类继承的a,还是子类自己新增的a?
b = 101; // 访问父类继承的b,还是子类自己新增的b?
c = 102; // 子类没有c,访问的肯定是从父类继承下来的c
// d = 103; // 编译失败,因为父类和子类都没有定义成员变量b
}
}

在这段代码中我们可以总结以下几点:
🎇如果访问的成员变量子类中有,优先访问自己的成员变量。
🎇如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
🎇如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
也就是说什么?就是说成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。这样是不是就很好理解了。

三、如果子类中存在与父类中相同的成员时,那如何在子类中访问父类相同名称的成员呢?
在这里面,我们又会引入一个新的概念叫做super这个关键字。而该关键字主要作用:在子类方法中访问父类的成员。代码如下:

public class Base {
int a;
int b;
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
public class Derived extends Base{
int a; // 与父类中成员变量同名且类型相同
char b; // 与父类中成员变量同名但类型不同
// 与父类中methodA()构成重载
public void methodA(int a) {
System.out.println("Derived中的method()方法");
}
// 与基类中methodB()构成重写(即原型一致,重写后序详细介绍)
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
// 对于同名的成员变量,直接访问时,访问的都是子类的
a = 100; // 等价于: this.a = 100;
b = 101; // 等价于: this.b = 101;
// 注意:this是当前对象的引用
// 访问父类的成员变量时,需要借助super关键字
// super是获取到子类对象中从基类继承下来的部分
super.a = 200;
super.b = 201;
// 父类和子类中构成重载的方法,直接可以通过参数列表区分清访问父类还是子类方法
methodA(); // 没有传参,访问父类中的methodA()
methodA(20); // 传递int参数,访问子类中的methodA(int)
// 如果在子类中要访问重写的基类方法,则需要借助super关键字
methodB(); // 直接访问,则永远访问到的都是子类中的methodA(),基类的无法访问到
super.methodB(); // 访问基类的methodB()
}
}

我们通过代码可以知道,super和this都是这能再非静态方法中使用。

IV、构造方法

这个大家还有印象吧,没印象的可以康康我上一篇博客(类和对象)里面有对其的介绍。今天我们来讲说再继承关系中。我们在构造子类的时候,一定要先帮助父类构造。如何调用?且听我娓娓道来。

class Animal {
    public int age;
    public String name;

    public Animal() {

    }
    public Animal(int age, String name) {
        this.age = age;
        this.name = name;
    }

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

class Dog extends Animal {
    public Dog() {
        super();//这个可以省略不写,编译器会默认加上
    }
    public Dog(int age, String name) {
        super(age, name);
    }
}
public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "ww";
        dog.age = 2;
        dog.eat();
    }
}

我们可以看看这个代码,还是狗这个类继承了动物这个父类。我们可以总结出一下几点:

(1)若父类定义无参或者默认的构造方法,在子类构造方法第一行默认有一个super()的调用。
(2)假如说父类有一个带参数的构造方法,我们在子类需要写一个构造方法。就像父类已经写了一个构造方法了。编译器就不会再默认地给你提供。
(3)在子类构造方法中,用super()来调用父类构造时,必须时子类构造函数第一条语句。
(4)super()只能在子类构造方法中出现一次。

为了便于理解,我们来看下面两个截图:
在这里插入图片描述
在这里插入图片描述
这两张截图是不是很好地说明了父类构造方法和子类的关系,什么时候应该加什么时候又不需要。

V、关键字

我们来看截图的这段代码:
在这里插入图片描述
在这里插入图片描述

关键字总结:

🎃super只是一个关键字,最大的作用其实是在写代码的时候提供更好的可读性,代表调用父类的成员方法和成员变量,this和super都不能在静态方法中去使用。
🎃super只能指代直接的父类,且super()和this()不能同时存在(同时存在到底谁放在前面呢,编译器肯定迷糊啊)
🎃继承关系上,当我们构造子类的时候,一定要帮助父类优先构造。
🎃如果成员变量定义为final语法规定必须同时给定一个人初始值

两者之间又要很重要的不同点:

  1. this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用
  2. 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
  3. 在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造方法中出现
  4. 构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有

在内存中,他们的存储是这样的:
在这里插入图片描述
还有一个关键字叫final。final这个关键字有点类似于C语言中的const。比如说

final int a = 10;
a = 20;

这样就是错误滴,我们再来看:

final int[] array = {1, 2, 3};

数组前面我们加了一个final到底时数组里面数字不能改变还是说这个数组的地址不呢个吧改变呢?我们画一张图就很好理解了:
在这里插入图片描述

VI、执行顺序

小朋友你是否好奇无论是父类还是子类的方法。他们的执行顺序是怎样的,又静态方法的时候又是怎么样执行的。我们还是以动物和狗这一父类子类来描述:请欣赏代码:

class Animal {
    public int age;
    public String name;

    static {
        System.out.println("Animal static{}");
    }
    {
        System.out.println("Animal {}");
    }
    public Animal() {
        System.out.println("Animal {}");
    }
    public Animal(int age, String name) {
        this.age = age;
        this.name = name;
    }

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

class Dog extends Animal {
    static {
        System.out.println("Dog static{}");
    }
    {
        System.out.println("Dog {}");
    }
    public Dog() {
        System.out.println("DOG()");
    }
    public Dog(int age, String name) {
        super(age, name);
    }
}

public class Test2 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println("==================");
    }
}

我们通过上述代码可以当看到父类中有三个成员方法:
在这里插入图片描述
我们写在一起看到更清晰。子类中同样也有三个:
在这里插入图片描述
大家想想执行结果顺序是在怎样的呢?
公布答案:
1、4、2、3、5、6.运行结果:
在这里插入图片描述
从运行结果我们可以看出:

(1)父类优先子类执行。
(2)静态的最先执行。
(3)静态的只执行一次(下面马上来说)

我们在main函数里面再实例化new一个新的对象dog2,其他都不变,我们再来看看运行结果:

public class Test2 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println("==================");
        Dog dog2 = new Dog();
    }
}

在这里插入图片描述
欸,发现没有,两个static不见了。这说明啥啊,静态的只执行一次嘛。第二次就不执行了啊。是不是神奇,简单明了。

VII、继承方式

在现实生活中,事物之间的府关系是复杂的。人类中更是如此。
在这里插入图片描述
但在java中只支持集中继承方式:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
而多继承在Java里面时不支持的,不同于C++。最后我们注意:

时刻牢记, 我们写的类是现实事物的抽象. 而我们真正在公司中所遇到的项目往往业务比较复杂, 可能会涉及到
一系列复杂的概念, 都需要我们使用代码来表示, 所以我们真实项目中所写的类也会有很多. 类之间的关系也会
更加复杂.
但是即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层
次太多, 就需要考虑对代码进行重构了.
如果想从语法上进行限制继承, 就可以使用 final 关键字

总结

关于继承的知识我们就讲到这里,后面由继承又会延申到组合、多态等等,我会继续更新慢慢学习~感谢你们的支持。我慢慢地写,你们慢慢地读


阳光拨开乌云,风会在你那里等你
地铁带走人群,下一站会在那里等你
破碎带走完整,新的形状会在那里等你
在深地海底也由空气,气泡悬浮,从晦暗到灿烂,从细碎到淋漓,飘向力所能及地高度,看到独树一帜地风景。

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值