JavaSE:继承(通俗细节版)

一、定义

在生活中,我们会经常听到继承这个词语,例如:某某某继承了某某某的遗产,某某某继承了某某某的皇位......其实在Java中也是类似的。在Java中,继承,是将两个类的共性抽取出来,从而达到对代码的复用(重复使用),将这些共性再组成一个类,这两个类就叫做子类(派生类),而新组成的这个类,就叫做父类(基类、超类),当子类继承父类后,就会把父类的成员和方法全部继承。读到这里,相信大家还是不怎么懂的,接下来我会用代码来帮助大家理解。

二、代码简单实现继承

我们这里定义了两个类,分别猫类和狗类(其中extends为继承的关键字,表示继承关系):

而小猫小狗会有很多共同的特性,如:颜色、年龄、名字,以及行为方面的,如:睡觉......,于是我们便把这些特性抽取出来,来组成一个新的类(Animal):

于是Animal类便是Dog类和Cat类的父类,Dog类和Cat类便是Animal类的子类。

在这里我们需要注意以下几点:

1.在Java中一个子类只能继承一个父类,若继承多个父类,是会报错的(如图所示)。

2.若父类中的成员或方法是private来修饰的,那子类仍然会继承父类的这些成员或方法,但是无法访问。

如上图所示,我们将父类中的成员name改为private修饰,那么我们在子类中就无法访问这个成员(注意是继承了父类成员和方法,但是无法访问):

我们访问的话会变红报错(如上图所示)。

三、访问父类成员(以下以成员变量为例,方法也是一样的)

1、父类和子类成员变量不同名

我们可以直接访问从Big中继承的a和b:

运行结果:

2、父类和子类成员变量同名

当发生如下情况时:

此时,优先访问子类自己(其中super为关键字(下面会详细解释,要耐心看完哦),可直接访问父类):

我们分别打印子类和父类中的成员变量a,我们发现父类中的a为默认值0,子类中a的值为我们所赋的值1,故:当父类和子类成员变量同名,优先访问子类中的成员变量(就近原则)

但是,如果我们非要访问父类中的a成员呢?

很简单,我们只需要一个关键字---super(下面会详细解释,要耐心看完哦)

如下:

super.a便可访问父类中的成员变量,运行结果如下:

3、访问的成员变量父类和子类中都没有

如果访问的成员变量子类中没有,则访问父类中的,如果父类中也没有,则编译报错。

四、重载和重写

根据前期学习的JavaSE,我们初步的了解了重载,我们可能简单的认为重载只能在一个类中使用,其实不是这样的:(下图为Java官方给出的重载定义)

故子类和父类中,也可以构成重载。

当父类和子类中成员方法名字相同,而参数不同时,构成重载;

当父类和子类中成员方法名字以及参数相同时,构成重写;

五、super关键字

在Java中,由于设计的不好,或者特殊场景的需要,父类和子类中可能会存在相同名称的成员,如果我们要在子类方法中访问父类同名成员,我们就需要super关键字来访问。

我们需要注意以下几点:

1.super和this的区别

(以我们上面所写代码为例)

相同点:

(1)this是一个关键字,会优先访问子类自己的成员,如果没有,则再访问父类的。

(2)super也是一个关键字(并非引用),在代码层面起到易读的效果。

(3)都只能在类的非静态方法中使用,用来访问非静态成员方法和字段。

不同点:

(1)this,会优先访问子类自己的成员,如果没有,则再访问父类的。

(2)在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性。

(3)构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有。

2.super的使用

(1)super.data;访问父类的普通成员变量

(2)super.func();调用父类的普通成员方法

(3)super();调用父类的构造方法

注意事项:

1.super只能在非静态方法中使用

因为static修饰的成员方法是属于类的,和对象无关,在加载时就被调用,故静态的方法中不能使用super也不能使用this​​​​​​

2.在子类方法中,访问父类的成员变量和方法

六、使用 super();调用父类构造方法

在了解这点之前,我们先来看看这段代码:

我们发现,当我们在Animal类中写了一个带两个参数的构造方法后,Dog类有了报错警告,这是因为,我们没有对父类进行初始化,当我们写了带两个参数的构造方法后,系统便不再提供的不带参数的构造方法(父类即Animal类中),这时父类无法初始化,于是出现了错误,要知道对象属性的初始化一定得调用构造方法。

接下来,就需要suepr关键字出场了:

首先,我们在main方法中实例化子类对象时,将父类及子类成员要初始化的值通过参数传过去,接着在子类中用带参数构造方法接收,并用super来调用父类构造方法并传参,完成对父类成员的初始化。

-------可能大家心存疑问:可是没有调用带参数的构造方法之前也没有出错啊?我们也没有初始化啊,为什么调用了之后就会出错呢?

-------这是因为,系统默认帮我们调用了不带参数的构造方法,来完成了默认的初始化。如下图:

只是在我们看不见的地方,系统完成了默认初始化

我们打印name,便是默认初始化得值null:

七、继承关系上的执行顺序

相信在学static时,我们就已经知道static所修饰的在加载时就已经执行,那在继承上,执行顺序又是如何呢?

我们先来看以下代码:

我们来运行一下,看一下执行顺序如何:

通过分析执行结果,得出以下结论:

1、父类静态代码块优先于子类静态代码块执行,且是最早执行

2、父类实例代码块和父类构造方法紧接着执行

3、子类的实例代码块和子类构造方法紧接着再执行

4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

八、final关键字

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

1.修饰成员变量,表示常量(即不能被修改)

2.修饰类,则该类为密封类,不可再被其他类继承

九、组合

和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码复用的效果。

组合并没有涉及到特殊的语法 (诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段。

组合可用以下代码实现:

组合是has a的关系(...是...的一部分),比如:狗是动物,猫是动物

继承是is a的关系(...是...的),比如:老师是学校的一部分,学生是学校的一部分

这样可以帮助大家理解

说到这里,我们继承的内容就全部讲完了,

为了写好这篇博客,花费了博主很长的时间,

如果能够帮助到大家的话,

就留下您的赞吧

  • 26
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值