Java基础语法06-面向对象-继承
七、继承
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类中无需再定义这些属性和行为,只需要和抽取出来的类构成继承关系。
继承的好处
提高代码的复用性。
提高代码的扩展性。
类与类之间产生了关系,是学习多态的前提。例如:学生 is - a 人。
继承的格式(extends
)
【修饰符】 class 父类 {
...
}
【修饰符】 class 子类 extends 父类 {
...
}
继承的特点
1、Java只支持单继承,每一个子类只有一个直接父类
2、Java支持多层继承,父类还可以有父类
3、子类会继承父类所有特征,包括成员变量、成员方法,哪怕是私有的,私有的在子类中无法直接使用。
4、子类不会继承父类的代码块、构造器等。
5、但是子类一定会调用父类的实例初始化方法。
继承的特点一:成员变量
1、父类成员变量私有化(private)
父类中的成员,无论是公有(public)还是私有(private),均会被子类继承。
子类虽会继承父类私有(private)的成员,但子类不能对继承的私有成员直接进行访问,可通过继承的get/set方法进行访问。如图所示:
子类创建对象时,在堆内存中是要为从父类继承的成员变量分配内存空间。
2、父类子类成员变量重名
我们说父类的所有成员变量都会继承到子类中,那么如果子类出现与父类同名的成员变量会怎么样呢?
结论:
(1)当父类的成员变量私有化时,在子类中是无法直接访问的,所以是否重名不影响,如果想要访问父类的私有成员变量,只能通过父类的get/set方法访问;
(2)当父类的成员变量非私有时,在子类中可以直接访问,所以如果有重名时,就需要加“super."进行区别。
格式:super.父类成员变量名,但是前提条件,这个成员变量没有私有化。
说明:虽然我们可以区分父子类的重名成员变量,但是实际开发中,我们不建议这么干。
继承的特点二:成员方法
我们说父类的所有方法子类都会继承,但是当某个方法被继承到子类之后,子类觉得父类原来的实现不适合于子类,该怎么办呢?
1、方法重写
1.@Override:写在方法上面,用来检测是不是有效的正确覆盖重写。这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。建议保留
2.必须保证父子类之间方法的名称相同,参数列表也相同。
3.子类方法的返回值类型必须【小于等于】父类方法的返回值类型(小于其实就是是它的子类,例如:Student < Person)。
注意:如果返回值类型是基本数据类型和void,那么必须是相同
4.子类方法的权限必须【大于等于】父类方法的权限修饰符。 小扩展提示:public > protected > 缺省 > private
5.几种特殊的方法不能被重写
静态方法不能被重写
私有等在子类中不可见的方法不能被重写
final方法不能被重写
小贴士:重写时,用到super.父类成员方法,表示调用父类的成员方法。
继承的特点三:构造方法
当类之间产生了关系,其中各类中的构造方法,又产生了哪些影响呢?
首先我们要回忆两个事情,构造方法的定义格式和作用。
构造方法的名字是与类名一致的。
所以子类是无法继承父类构造方法的。
构造方法的作用是初始化实例变量的,而子类又会从父类继承所有成员变量
所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个
super()
,表示调用父类的实例初始化方法,父类成员变量初始化后,才可以给子类使用。
如果父类没有无参构造怎么办?
解决办法:在子类构造器中,用super(实参列表),显示调用父类的有参构造解决。
结论:
子类对象实例化过程中必须先完成从父类继承的成员变量的实例初始化,这个过程是通过调用父类的实例初始化方法来完成的。
super():表示调用父类的无参实例初始化方法,要求父类必须有无参构造,而且可以省略不写;
super(实参列表):表示调用父类的有参实例初始化方法,当父类没有无参构造时,子类的构造器首行必须写super(实参列表)来明确调用父类的哪个有参构造(其实是调用该构造器对应的实例初始方法)
super()和super(实参列表)都只能出现在子类构造器的首行
继承的特点四:单继承限制
1、Java只支持单继承,不支持多继承。
2、Java支持多层继承(继承体系)。
顶层父类是Object类。所有的类默认继承Object,作为父类。
3、子类和父类是一种相对的概念。
4、一个父类可以同时拥有多个子类
final关键字
final:最终的,不可更改的,它的用法有:
1、修饰类
表示这个类不能被继承,没有子类
2、修饰方法
表示这个方法不能被子类重写
3、声明常量
final修饰某个变量(成员变量或局部变量),表示它的值就不能被修改,即常量,常量名建议使用大写字母。
如果某个成员变量用final修饰后,没有set方法,并且必须初始化(可以显式赋值、或在初始化块赋值、实例变量还可以在构造器中赋值)
当修饰的是数组变量时,数组的地址值不可以改变但数组元素可以改变。
this关键字
this代表当前对象的引用(地址值),即对象自己的引用。
this可以用于非静态代码块和构造器中:表示正在创建的那个实例对象,即正在new谁,this就代表谁
this用于实例方法中:表示调用该方法的对象,即谁在调用,this就代表谁。
this使用格式
1、this.成员变量名
当方法的局部变量与当前对象的成员变量重名时,就可以在成员变量前面加this.,如果没有重名问题,就可以省略this.
2、this.成员方法
调用当前对象自己的成员方法时,都可以加"this.",也可以省略,实际开发中都省略
3、this()或this(实参列表)
当需要调用本类的其他构造器时,就可以使用该形式。
要求:
必须在构造器的首行
如果一个类中声明了n个构造器,则最多有 n - 1个构造器中使用了"this(【实参列表】)",否则会发生递归调用死循环
super关键字
super代表父类的引用
注意:在子类中通过super去引用父类的成员时,必须保证该成员在子类中是仍然可见的,即注意权限修饰符问题
(1)super.成员变量
在子类中访问父类的成员变量,特别是当子类的成员变量与父类的成员变量重名时。
(2)super.成员方法
在子类中调用父类的成员方法,特别是当子类重写了父类的成员方法时
(3)super()或super(实参列表)
在子类的构造器首行,用于表示调用父类的哪个构造器(本质上是该构造器对应的实例初始化方法)
super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。
this()和this(实参列表) 与 super()或super(实参列表) 不能同时出现
就近原则:解决复杂问题
没有super和this
在构造器、代码块、方法中如果出现使用某个变量,先查看是否是当前块声明的局部变量,
如果不是局部变量,先从当前类去找成员变量
如果当前类中没有找到,会往上找父类的(非private,跨包还不能是缺省的)
this :代表当前对象的引用。
通过this找成员变量和成员方法时,先从当前类中找,没有的会往上找父类的(非private,跨包还不能是缺省的)。
但是this()或this(实参列表)只会在本类中找
super :代表父类的存储空间标识(可以理解为父类的引用)。
通过super找成员变量和成员方法时,直接从父类空间(包含父类的父类继承的)找
super()或super(实参列表)只能从直接父类找
通过super只能访问父类在子类中可见的(非private,跨包还不能是缺省的)
即:super一定是从直接父类开始找
this一定是从当前类的成员开始找
即没有this又没有super,一定是从局部变量开始找
注意:super和this都不能出现在静态方法和静态代码块中,因为super和this都是存在与对象中的
继承与初始化
类初始化
实际上,类初始化的过程时在调用一个<clinit>()方法,而这个方法是编译器自动生成的。编译器会将如下两部分的所有代码,按顺序合并到类初始化<clinit>()方法体中。
(1)静态类成员变量的显式赋值语句
(2)静态代码块中的语句
整个类初始化只会进行一次,如果子类初始化时,发现父类没有初始化,那么会先初始化父类。
结论:
每一个类都有一个类初始化方法<clinit>()方法,然后子类初始化时,如果发现父类没有加载和没有初始化,会先加载和初始化父类,然后再加载和初始化子类。一个类,只会初始化一次。
实例初始化
实际上我们编写的代码在编译时,会自动处理代码,整理出一个<clinit>()的类初始化方法,还会整理出一个或多个的<init>(...)实例初始化方法。一个类有几个实例初始化方法,由这个类有几个构造器决定。
实例初始化方法的方法体,由四部分构成:
(1)super()或super(实参列表) 这里选择哪个,看原来构造器首行是哪句,没写,默认就是super()
(2)非静态实例变量的显示赋值语句
(3)非静态代码块
(4)对应构造器中的代码
特别说明:其中(2)和(3)是按顺序合并的,(1)一定在最前面(4)一定在最后面
执行特点:
创建对象时,才会执行,
调用哪个构造器,就是指定它对应的实例初始化方法
创建子类对象时,父类对应的实例初始化会被先执行(父类的clinit<>(有参或无参)方法执行完后再执行子类的init<>(有参或无参)方法),执行父类哪个实例初始化方法,看用super()还是super(实参列表)
结论:
类初始化肯定优先于实例初始化。
类初始化只做一次。
实例初始化是每次创建对象都要进行。
Java基础语法06-面向对象-继承的更多相关文章
- Java基础语法(9)-面向对象之类的成员
title: Java基础语法(9)-面向对象之类的成员 blog: CSDN data: Java学习路线及视频 1.面向对象特征--封装 为什么需要封装?封装的作用和含义? 我要用洗衣机,只需要按 ...
- Java基础语法(10)-面向对象之三大特征
title: Java基础语法(9)-面向对象之类的成员 blog: CSDN data: Java学习路线及视频 1.面向对象特征--封装 为什么需要封装?封装的作用和含义? 我要用洗衣机,只需要按 ...
- 056 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 03 一维数组的应用
056 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 03 一维数组的应用 本文知识点:数组的实际应用 程序开发中如何应用数组? 程序代码及其运行结果: 不同数据类 ...
- 055 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 02 数组的概念
055 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 02 数组的概念 本文知识点:数组的概念 数组的声明创建.初始化 在学习数组的声明创建.初始化前,我们可以和之 ...
- Java基础语法(11)-面向对象之关键字
title: Java基础语法(11)-面向对象之关键字 blog: CSDN data: Java学习路线及视频 1.this this是什么 它在方法内部使用,即这个方法所属对象的引用: clas ...
- 061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结
061 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 08 一维数组总结 本文知识点:一维数组总结 总结 注意点
- 060 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 07 冒泡排序
060 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 07 冒泡排序 本文知识点:冒泡排序 冒泡排序 实际案例分析冒泡排序流程 第1轮比较: 第1轮比较的结果:把最 ...
- 059 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 06 增强型for循环
059 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 06 增强型for循环 本文知识点:增强型for循环 增强型for循环格式 案例练习增强型for循环 数组名字 ...
- 058 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 05 案例:求数组元素的最大值
058 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 05 案例:求数组元素的最大值 本文知识点:求数组元素的最大值 案例:求数组元素的最大值 程序代码及其执行过程 ...
- 057 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 04 案例:求整型数组的数组元素的元素值累加和
057 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 04 案例:求整型数组的数组元素的元素值累加和 本文知识点:求整型数组的数组元素的元素值累加和 案例:求整型数 ...
随机推荐
- 循环双向链表-C语言实现
直接贴出完整代码,每个函数的功能及部分代码的解释都在注释中,代码亲测可行 /* 2018.8.15 注意三点: 1.不要将循环写成if //很尴尬,主要是我犯了这个错误,找了半天还没找出来,第二天看的 ...
- Java修炼——对象数组存储表格数据
数组存基本数据类型,也可以存引用数据类型 对象数组:使用数组存储对象(自定义对象) 先定义Person的三个私有变量,给他取值赋值方法,重写toString方法. package com.bjsxt. ...
- 洛谷P2569 (BZOJ1855)[SCOI2010]股票交易 【单调队列优化DP】
Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价 ...
- HashMap的常见问题
关于HashMap的一些常见的问题,自己总结一下: 首选HashMap在jdk1.7和jdk1.8里面的实现是不同的,在jdk1.7中HashMap的底层实现是通过数组+链表的形式实现的,在jdk1. ...
- Koa - 使用koa-multer上传文件(上传限制、错误处理)
前言 上传文件在开发中是很常见的操作,今天我选择使用koa-multer中间件来实现这一功能,除了上传文件外,我还会对文件上传进行限制,以及发生上传错误时的处理. 由于原来的 koa-multer 已 ...
- linux google protobuf
说明: protobuf已经全面迁移到github,地址:https://github.com/google/protobuf 直接下载2.6.1版本:https://github.com/googl ...
- Python3 网络基础基础2
目录 subprocess 粘包问题 问题原因 解决问题 上传大文件 UDP协议 SocketServer subprocess 可以通过代码执行操作系统的终端命令, 并返回终端执行命令后的结果 im ...
- 聊聊技术选型 - Angular2 vs Vue2
作者介绍:李旸,美团点评前端工程师,3 年 Web 前端开发经验,现在是美团点评点餐团队的一员. "Come, and take choice of all my library, And ...
- markdownPad在win10下渲染报错问题
今天使用MarkdownPad 2,打开后发现预览效果出错了,本来以为自己下载了破解版的缘故导致软件不稳定,后来查找了网上,发现这是一个普遍的问题,根据软件的提示来到官方FAQ页面,找到解决方法. 实 ...
- 每天用Mybatis,但是Mybatis的工作原理你真的知道吗?
近来想写一个mybatis的分页插件,但是在写插件之前肯定要了解一下mybatis具体的工作原理吧,于是边参考别人的博客,边看源码就开干了. 核心部件: SqlSession Executor Sta ...