菜鸡的Java笔记 第十九 - java 继承
继承性的主要目的,继承的实现,继承的限制
继承是面向对象中的第二大主要特点,其核心的本质在于:可以将父类的功能一直沿用下去
为什么需要继承?
那么为了更好的区分出之前学习的概念与现在程序的区别,下面通过两个具体的代码来进行研究
例如:现在有俩个类:Person,Student,按照原始的方式,程序代码实现如下:
- class Person{
- private String name;
- private int age;
- public void setName(String name){
- this.name = name;
- }
- public void setAge(int age){
- this.age = age;
- }
- public String getName(){
- return this.name;
- }
- public int getAge(){
- return this.age;
- }
- }
- class Student{
- private String name;
- private int age;
- private String school;
- public void setName(String name){
- this.name = name;
- }
- public void setAge(int age){
- this.age = age;
- }
- public void setSchool(String school){
- this.school = school;
- }
- public String getName(){
- return this.name;
- }
- public int getAge(){
- return this.age;
- }
- public String getSchool(){
- return this.school;
- }
- }
- public class inherit{
- public static void main(String args[]){
- System.out.println();
- }
- }
两个类出现有重复,而且最为关键的问题是学生从现实的角度来看一定是个人
那么按照这样的理解就可以发现出现重复的核心问题所在了,就是两个类之间没有联系
之前所编写的代码或者说之前所学习到的概念那么还不足以解决多个类之间的代码重复消除问题
Student 是比 Person 更加细化的定义范畴
使用继承解决问题
在java中可以利用继承的概念来实现父类代码的重用问题,程序中可以使用extennds 关键字实现继承操作的定义
其使用的语法如下:
class 子类 extends 父类{}
需要注意点名词概念:
子类:也被称为派生类
extends虽然从本质上来讲属于继承概念,但是其翻译为扩展,扩充的意思
父类 本质上在java中称为超类(Super Class)
范例:继承的基本使用
- class Person{
- private String name;
- private int age;
- public void setName(String name){
- this.name = name;
- }
- public void setAge(int age){
- this.age = age;
- }
- public String getName(){
- return this.name;
- }
- public int getAge(){
- return this.age;
- }
- }
- class Student extends Person{ // Student 是Person 的子类
- // 此时并没有在Student类里面定义任何的操作
- }
- public class inherit{
- public static void main(String args[]){
- Student stu = new Student();// 实例化子类对象
- stu.setName("少爷");//通过Person类继承而来
- stu.setAge(20);//通过Person类继承而来
- System.out.println("姓名:"+stu.getName+",年龄:"+stu.getAge());
- }
- }
- /*
- 结果
- 姓名:少爷,年龄:20
- */
通过以上的程序就可以发现一点:子类在继承了父类之中,那么对于父类的支持方法不会减少
但是子类可以进一步扩充属于自己的属性与方法
范例:继承的基本使用
- class Person{
- private String name;
- private int age;
- public void setName(String name){
- this.name = name;
- }
- public void setAge(int age){
- this.age = age;
- }
- public String getName(){
- return this.name;
- }
- public int getAge(){
- return this.age;
- }
- }
- class Student extends Person{ // Student 是Person 的子类
- private String school; // 子类自己扩充的属性
- public void setSchool(String school){
- this.school = school;
- }
- public String getSchool(){
- return this.school;
- }
- public class inherit{
- public static void main(String args[]){
- Student stu = new Student();// 实例化子类对象
- stu.setName("少爷");//通过Person类继承而来
- stu.setAge(20);//通过Person类继承而来
- stu.setSchool("清华");//子类自己扩充的属性
- System.out.println("姓名:"+stu.getName+",年龄:"+stu.getAge()+",学校:"+stu.getSchool());
- }
- }
- /*
- 结果
- 姓名:少爷,年龄:20,学校:五道口
- */
通过这样的继承实现发现:
父类的功能可以延续到子类继续使用,这样在某些父类不能够修改的情况下,就可以通过继承来实现功能的扩充
子类中至少可以维持父类的原始方法不变,也就是说在子类里面父类的方法功能不会减少
*/
/* 继承的使用限制
虽然继承的核心目的在于扩充类中的已有功能,但是在实际的开发之中,继承的使用也是存在有诺干限制的,这些限制必须注意
限制一:java不允许多重继承,也就是说一个子类只能够继承一个父类
因为C++它支持多继承,也就是说一个子类可以同时继承多个父类
范例:错误代码
- class A{
- }
- class B{
- }
- class C extendsa A,B{
- }
- public class inherit{
- public static void main(String args[]){
- System.out.println();
- }
- }
那么为什么实际中会出现这种代码呢?
其实本质上也只是希望C类可以同时继承A,B类的方法,但是由于这样的做法与现实生活有冲突,所以从java的角度就屏蔽了,但是有解决方案
虽然java不允许多重继承,但是却允许多层继承,以下代码为方案:
- class A{
- }
- class Bextendsa A{
- }
- class C extendsa B{
- }
- public class inherit{
- public static void main(String args[]){
- System.out.println();
- }
- }
此时的C类实际上就具备有A,B类的全部定义,但是从实际的开发,这种继承的层次关系不要超过三层
限制二:子类在继承父类之后会将父类中的全部结构继承下来,但是对于私有的操作属于隐式继承(子类不能直接调用),而所有的非私有操作属于显式继承(可以直接调用)
范例:观察显式继承
- class A{
- private String name:
- public void setName(String name){
- this.name = name;
- }
- public String getName(){
- return this.name;
- }
- }
- class B extendsa A{
- }
- public class inherit{
- public static void main(String args[]){
- B b= new B();
- b.setName("少爷");
- System.out.println(b.getName());
- }
- }
现在对于子类B而言是存在name属性的,但是这个属性子类并不能够直接操作
范例:子类B直接访问
- class A{
- private String name:
- public void setName(String name){
- this.name = name;
- }
- public String getName(){
- return this.name;
- }
- }
- class B extendsa A{
- public void print(){
- System.out.println(name);
- }
- }
- public class inherit{
- public static void main(String args[]){
- B b= new B();
- b.setName("少爷");
- System.out.println(b.getName());
- }
- }//结果程序出错
也就是说此时的name属于隐式继承,而所有的setter方法属于显式继承,显式继承可以直接调用,而隐式继承的只能够间接的操作或者不能够操作
限制三:在实例化子类对象时会默认调用子类的无参构造方法,但是在执行子类构造前会首先自动实例化父类构造为父类的对象实例化,也就是说父类对象永远早于子类对象的实例化
范例:观察实例化过程
- class A{
- public A(){
- System.out.println("***********************");
- }
- }
- class B extends A{
- public B(){
- System.out.println("###########################");
- }
- }
- public class inherit{
- public static void main(String args[]){
- B b= new B();
- }
- }
- /*
- 结果:
- ***********************
- ###########################
- */
如果说现在非要为子类加上一个调用父类构造的标记,那么就可以使用“super()”的形式完成
- class A{
- public A(){
- System.out.println("***********************");
- }
- }
- class B extends A{
- public B(){
- super(); // 表示由子类构造调用父类构造
- System.out.println("###########################");
- }
- }
- public class inherit{
- public static void main(String args[]){
- B b= new B();
- }
- }
- /*
- 结果:
- ***********************
- ###########################
- */
也就是证明,在子类的构造之中其实一直隐藏了一行“super()”语句,但是在进行无参父类构造调用的时候,写上“super()”是没有意义的
往往是在父类没有提供无参构造时使用的
范例:错误代码
- class A{
- public A(String name){
- System.out.println("***********************");
- }
- }
- class B extends A{
- public B(){
- // super(); // 表示由子类构造调用父类构造
- System.out.println("###########################");
- }
- }
- public class inherit{
- public static void main(String args[]){
- B b= new B();
- }
- }//结果程序出错
这个时候很明显使用隐含的“super()”并不合适,所以应该明确的调用指定参数的构造方法
- class A{
- public A(String name){
- System.out.println("***********************");
- }
- }
- class B extends A{
- public B(String name){
- super(name); // 表示由子类构造调用父类构造
- System.out.println("###########################");
- }
- }
- public class inherit{
- public static void main(String args[]){
- B b= new B("少爷");
- }
- }
在大多数情况下父类一般都会提供有无参构造方法,这个时候可以在子类构造中不出现“super()”的语句
但是如果此时父类没有提供无参构造方法,那么子类就必须使用“super()”调用指定参数的构造方法
对于 super 调用构造方法的情况需要注意如下几项:
不管你子类怎么折腾都一定要去调用父类的构造方法,即:调用父类构造使用 super()
super() 是在子类中编写的,表示通过子类的构造方法去调用父类构造,必须放在子类构造方法的首行,不能与“this()”不能同时出现在构造方法之中,两者关系属于二选一
如果现在父类中没有提供无参构造方法,那么在子类构造之中必须明确的调用有参构造方法,必须使用 super 调用指定参数的父类构造
this 是应用在本类的关键字,而 super 是应用在子类中的关键字,利用 super 找到父类结构
分析:关于this()与super()的问题
在之前学习过this()表示调用本类的其他构造方法,而现在有了继承关系之后,可以使用super() 由子类调用父类中指定的构造方法,并且这两个语句都一定要出现在首行,也就是说这两个语句不能同时出现
范例:不让子类调用父类的构造
- class A{
- public A(String name){
- System.out.println("***********************");
- }
- }
- class B extends A{
- public B(){
- }
- public B(String name){
- this();//
- System.out.println("###########################");
- }
- }
- public class inherit{
- public static void main(String args[]){
- B b= new B("少爷");
- }
- }
在子类的构造方法中出现了“this()”,这样就不会出现“super()”的默认执行而转为调用本类的构造方法了
那么这样是不是可以不调用父类构造了呢?
总结
1.继承的唯一好处就是进行了功能的扩充,并且java只支持单继承局限
2.子类对象实例化时一定要先实例化父类对象,而后在实例化子类自己的对象
*/
菜鸡的Java笔记 第十九 - java 继承的更多相关文章
- 菜鸡的Java笔记 第二十九 - java 单例设计模式
SingleCase 单例设计模式 1.单例设计模式的特点 2.多例设计模式的特点 内容 单例设计模式 现在如果说有这么一个程序类 class S ...
- Java进阶(三十九)Java集合类的排序,查找,替换操作
Java进阶(三十九)Java集合类的排序,查找,替换操作 前言 在Java方向校招过程中,经常会遇到将输入转换为数组的情况,而我们通常使用ArrayList来表示动态数组.获取到ArrayList对 ...
- 菜鸡的Java笔记 第二十八 - java 包的定义
包的主要作用以及定义 包的导入操作 系统常见的开发包 jar 程序命令 包的定义 在任何的操作系统之中都有一个统一的共识:同一个目录下不能够存在有相同的文 ...
- Java笔记(二十九)……网络编程
概述 网络模型 网络通讯的要素 ip地址:网络中设备的标识符 端口:用于标识同一台设备上不同的进程,有效端口:0~65535,其中0~1024是系统使用端口或者保留端口 TCP与UDP UDP特点: ...
- 菜鸡的Java笔记 第二十六 - java 内部类
/* innerClass 从实际的开发来看,真正写到内部类的时候是在很久以后了,短期内如果是自己编写代码,几乎是见不到内部类出现的 讲解它的目的第一个是为了解释概念 ...
- 菜鸡的Java笔记 第二十四 - java 接口的基本定义
1.接口的基本定义以及使用形式 2.与接口有关的设计模式的初步认识 3.接口与抽象类的区别 接口与抽象类相比,接口的使用几率是最高的,所有的 ...
- 菜鸡的Java笔记 第二十二 - java 对象多态性
本次只是围绕着多态性的概念来进行讲解,但是所讲解的代码与实际的开发几乎没有关系,而且多态一定是在继承性的基础上才可以操作的, 而本次将使用类继承的关系来描述多态的性质,实际的开发中不会出 ...
- 菜鸡的Java笔记 第十八 - java 代码块
代码块 code block content (内容) 在程序结构之中使用"{}"定义的内容就称为代码块,但是会根据其声明的位置以及关 ...
- 菜鸡的Java笔记 第十六 - java 引用传递
referenceDelivery 引用传递是整个java 的精髓,也是所有初学者最难学的地方 引用的本质:同一块堆内存可以被不同的栈内存所指向 下面通过三道程序来进行引用传 ...
随机推荐
- windows使用VS编译python源码
使用VS2021编译python源码 说明,使用VS2019也是可以的. 环境准备 对于VS2019首要要安装必要的环境 到python官网下载源码压缩包以及解压(红色箭头任选一个都行) 打开下载好的 ...
- 感恩笔记之SQL查询功能最简使用模板
感恩笔记之SQL查询功能最简使用模板 第一部分:SQL单表功能 1 语句主要关键字 SELECT --查询数据列 INTO --新建数据表 FROM --查询数据表 WHERE --筛选数据表结果 O ...
- 踩坑系列《八》解决Win10没有找到Hyper-v的错误
最近要安装docker,所以得开启Hyper属性面板,找了下,发现电脑上没有看到该属性. 在这之前,得先判断,你电脑是不是支持Hyper,打开cmd窗口,输入systeminfo 看看最下面Hyper ...
- 【Docker】(9)---每天5分钟玩转 Docker 容器技术之镜像
镜像是 Docker 容器的基石,容器是镜像的运行实例,有了镜像才能启动容器.为什么我们要讨论镜像的内部结构? 如果只是使用镜像,当然不需要了解,直接通过 docker 命令下载和运行就可以了. 但如 ...
- 题解 [NOI2019]弹跳
题目传送门 题目大意 给出 \(n\) 做城市,每座城市都有横纵坐标 \(x,y\).现在给出 \(m\) 个限制 \(p,t,l,r,d,u\),表示从 \(p\) 城市出发,可以花费 \(t\) ...
- 阿里云服务器上在docker部署jenkins
1.查询jenkins:docker search jenkins 2.拉取jenkins镜像 docker pull jenkins/jenkins:lts 3.新建jenkins的工作目录: mk ...
- Dapr + .NET Core实战(十四)虚拟机集群部署 mDNS + Consul
前面我们说了在单机模式下和K8S集群下的Dapr实战,这次我们来看看如何在不使用K8S的情况下,在一个传统的虚拟机集群里来部署Dapr. 1.环境准备 我们准备两台centos7虚拟机 Dapr1:1 ...
- repartition导致的广播失败,关于错误Failed to get broadcast_544_piece0 of broadcast_544
今天一个生产环境任务出现了性能问题,,经过仔细检查发现是在一个join操作时,原设定广播右表数据广播失败,导致后续步骤进行缓慢,,报错信息 java.io.IOException: org.apach ...
- Github 29K Star的开源对象存储方案——Minio入门宝典
对象存储不是什么新技术了,但是从来都没有被替代掉.为什么?在这个大数据发展迅速地时代,数据已经不单单是简单的文本数据了,每天有大量的图片,视频数据产生,在短视频火爆的今天,这个数量还在增加.有数据表明 ...
- Java:反射小记
Java:反射小记 对 Java 中的 反射,做一个微不足道的小小小小记 概念 Java 反射指的是在 Java 程序运行状态中,对于任何一个类,都可以获得这个类的所有属性和方法:对于给定的一个对象, ...