篮球哥温馨提示:编程的同时不要忘记锻炼哦!

伴着秋风,聆听篮球落网的声音


目录

1、继承

1.1 继承的概念

1.2 继承的语法和简单使用

1.3 子类中访问父类成员出现同名

2、 super关键字

2.1 如何使用 super 关键字

2.2 子类构造方法

2.3 super 和 this 的区别

3、再谈代码块

3.1 回顾

3.2 继承关系中的执行顺序

4、 protected 关键字

4.1 protected关键字的作用

4.2 子类如何访问父类 private 修饰的成员?

4.3 为什么 private 和 protected 不能修饰外部类?

5、Java中的继承方式

6、final 关键字

7、继承与组合


1、继承

1.1 继承的概念

这里我们回顾下之前 Student 类,如果今天我们要定义一个 Teacher 类,我们会发现,这两个类有很多共同点:首先学生有姓名性别年龄,老师也有姓名性别年龄,同时学生的行为有上课,老师的行为也有上课这一行为,但是呢,学生与老师又有不同的点,比如学生有成绩,而老师有工资,再比如学生有考试的行为,而老师却有改试卷的行为,所以我们再一想,他们共同的点是不是可以抽取出来形成一个新的类?

继承(inheritance)机制:这个机制是面向对象程序设计中一个可以使代码复用的重要手段,他可以在原有类的特性上进行扩展,增加新的功能,由继承下来的类,称为派生类,从而实现代码复用,就比如我们上面的 Student 和 Teacher 类,抽出共同的部分,然后继承共同的部分,达到代码复用:

通过上图我们发现 Student 和 Teacher 类都继承了 Person 类的属性,其中 Person 称为父类/基类/超类,而 Student,Teacher 可以称为 Person 的子类/派生类,继承之后,子类可以复用父类中的成员,而子类只需要关心自己新增加的成员即可,同时也可以看出,继承最大的作用就是实现代码复用和实现多态(多态下期讲)

1.2 继承的语法和简单使用

现在我们是有了这样的一个思路,如何用代码实现呢?这里我们需要了解 extends 关键字,具体的语法如下:

修饰符 class A extends B {// ...
}

而如上代码中,我们就可以理解成,A类继承了B类,所以A是B的子类,B是A的父类,那我们讲我们上图中画的图用代码实现一下:

public class Person {public String name;public String sex;public int age;//老师和学生都需要吃饭和上课public void attendClass() {System.out.println(name + "正在上课");}public void eat() {System.out.println(name + "正在吃饭");}
}
class Student extends Person {//学生有成绩public float score;//学生需要考试public void examination() {System.out.println(name + "同学正在考试");}
}
class Teacher extends Person {//老师有工资public float salary;//老师需要改试卷public void modifyPaper() {System.out.println(name + "老师正在改试卷");}
}

我们先分析下上面的代码:首先 Student 和 Teacher 分别继承了 Person 这个类,也就是说他们继承了父类的成员,所以子类中有两部分,第一部分是父类的成员,第二部分是子类自己的成员,简而言之,就是通过子类实例化的对象的成员里面包含了父类成员。

在一个我们可以观察下他们抽取出来的部分,确实是如我们刚开始所说,把学生和老师共同拥有的属性和行为抽取出来形成一个人的类,接下来我们就用main方法去测试下他们:

class Test {public static void main(String[] args) {Student student = new Student();student.name = "张三";student.examination();Teacher teacher = new Teacher();teacher.name = "李四";teacher.modifyPaper();student.eat();teacher.eat();}
}

从这个打印结果也能证明我们前面的结论,子类实例化的对象确实继承了父类的属性和行为!

总结:

  • 子类会将父类中的成员继承到子类中
  • 子类继承父类后,必须要添加自己特有的成员,体现出与父类的不同,否则就没有必要继承了

1.3 子类中访问父类成员出现同名

上面的演示我们也看到了,子类是可以访问父类的成员的(建立在限定符允许的情况,后面讲),那如果出现子类的成员变量和父类成员变量同名怎么办呢?如果成员方法也同名怎么办?

我们简单对上面的学生类做修改:

class Student extends Person {//学生有成绩public float score;public String name = "123";//学生需要考试public void examination() {System.out.println(name + "同学正在考试");}public void eat() {System.out.println("执行了子类的eat");}
}
class Test {public static void main(String[] args) {Student student = new Student();student.examination();student.eat();}
}

这个代码里面的 name 变量和 eat 方法跟父类里的同名了:

如果同名执行的是父类的话,则打印的是:null同学正在考试 和 null正在吃饭 因为如果执行父类则 name 变量没有初始化,默认值是 null。

如果同名执行的是子类的话,则打印的是:123同学正在考试 和 执行了子类的eat 因为我们原地初始化了子类的 name 变量为"123",我们让main方法走起来:

总结: 

  • 如果子类成员变量和父类成员变量同名,则优先访问子类的
  • 成员变量优先访问遵循就近原则,自己有优先自己的,自己没有则向父类中找,都没有则报错
  • 如果子类成员方法和父类成员方法同名(没有构成重载),则优先访问子类的
  • 如果子类成员方法和父类成员方法同名(构成了重载),则根据调用方法传递的参数选择合适的成员访问,都没有则报错

如果在子类中存在与父类相同的成员时,我非要访问父类的,怎么办?用super关键字,我们马上了解


2、 super关键字

2.1 如何使用 super 关键字

由于场景的需要,可能会出现父类和子类出现相同名字的成员,如果我们要在子类中访问相同名字的父类成员,直接访问是不可以做到的,这里就可以使用 super 关键字,我们把上面的代码稍作修改:

class Student extends Person {//学生有成绩public float score;public String name = "123";//学生需要考试public void examination() {System.out.println(super.name + "同学正在考试");}public void eat() {System.out.println("执行了子类的eat");}public void test() {super.eat();}
}
class Test {public static void main(String[] args) {Student student = new Student();student.examination();student.test();}
}

如果说 super 可以当子类和父类成员出现同名加上 super 会帮我们访问父类的话,则会打印 null同学正在考试 和 null正在吃饭 我们来看看是不是真的帮我们访问的父类成员:

注意:

  • super 只能在非静态方法中使用,因为只有产生了对象才能访问实例成员变量和成员方法,而静态成员变量和静态成员方法是不依赖于对象的
  • 在子类方法中,访问父类的成员变量或者成员方法
  • super 调用构造方法后面讲

2.2 子类构造方法

之前我们了解过,当创建对象的时候,先要调用类的构造方法,当构造方法调用完毕,对象才真正产生了,那么在我们实例化子类的时候,子类既然要继承父类的属性,需先调用父类的构造方法,然后再执行子类的构造方法,所以当我们什么构造方法都没写的时候,编译器会默认提供无参的构造方法。

既然实例化子类的时候需要先调用父类的构造方法,所以编译器默认给子类提供的构造方法就是这样的:

public Student() {super();}

也就是说,子类构造方法中,如果用户没有写,编译器会默认调用父类的无参构造方法: super();而且 super();必须是构造方法中的第一条语句,并且只能出现一次。

这里我们做个测试,证明没有写自己写 super();的时候编译器会默认调用:

public class Person {public String name;public String sex;public int age;public Person() {System.out.println("父类构造方法执行!");}
}class Student extends Person {public float score;public Student() {System.out.println("子类构造方法执行!");}
}

总结:子类虽然没有调用父类构造方法,但编译器还是默认带上了, 同时也正如我们所说,先调用父类在调用子类,因为子类对象中的成员有两部分组成,分别是父类继承下来的部分以及子类自己增加的部分,字面意思父子,肯定是现有父后有子,所以在子类实例化的时候,必须先调用父类的构造方法,将父类继承下来的成员构造完整之后,在调用子类的构造方法,将子类自己的成员初始化完整。

注意:

  • 在子类构造方法中,编译器虽然隐含了super() 调用,但是如果父类构造方法是有参的,则需要子类构造方法里显式提供合适父类构造方法的调用
  • super(...) 只能在子类构造方法出现一次,不能和 this 同时出现

2.3 super 和 this 的区别

这个其实也是面试会问到的一个题,下面我们就来看下他们的区别:

相同点:

  • 都是Java中的关键字
  • 都只能在类的非静态方法中使用,用来访问非静态成员和变量
  • 在构造方法中出现的话,必须是构造方法中的第一条语句,而且他俩不能同时出现

不同点:

  • this 是当前对象的引用,而 super 是从父类继承下来部分成员的引用,不能说是父类对象的引用,因为实例化子类的时候并没有创建父类的对象
  • this 用来访问本类的方法和属性,super 用来访问父类的方法和属性(都是非静态)
  • 在构造方法中,this 用来调用本类的构造方法,super 用来调用父类的构造方法
  • 子类构造方法中,super 一定会出现,this 如果不写则没有

图示例:


3、再谈代码块

3.1 回顾

上期我们测试过代码块,发现执行顺序的优先级分别是 静态代码块 -> 实例代码块 -> 构造方法 分别是这种执行循序。

  • 静态代码块最先执行,并且只执行一次,因为是再JVM加载类的时候就开辟了。
  • 当有对象创建时就会执行实例代码块,实例代码块执行完毕后,接着执行构造方法

3.2 继承关系中的执行顺序

如果父类中有静态代码块,实例代码块,构造方法,而子类中也有这些,那么他们的先后执行顺序是什么呢?我们用代码来做测试:

public class Person {public String name;public String sex;public int age;{System.out.println("执行 Person 实例代码块!");}static {System.out.println("执行 Person 静态代码块!");}public Person() {System.out.println("执行 Person 构造方法!");}
}
class Student extends Person {public float score;{System.out.println("执行 Student 实例代码块!");}static {System.out.println("执行 Student 静态代码块!");}public Student() {System.out.println("执行 Student 构造方法!");}
}
class Test {public static void main(String[] args) {Student student = new Student();}
}

通过测试,我们可以得出以下结论:

  • 静态代码块永远是最早执行,但是父类优于子类
  • 紧接着就是父类实例代码块和构造方法,再就是子类实例代码块和构造方法
  • 第二次实例化的时候,父类和子类静态代码块将不会执行(可以自己下去测试,上一期也测试)

4、 protected 关键字

4.1 protected关键字的作用

其实在上一期中我们就已经简单的介绍了以下这个关键字,只是当时我们并不知道继承的概念,所以当时出现,允许在不同包中的子类中访问这个权限,相信大家目前应该已经了解他的权限了,那这里我们就做一个小的代码演示:

看到这,相信你就理解了 protected 关键字了,建议大家自己下来多尝试敲代码,多测试,简单来说,要想在不同的包中访问 protected 修饰的成员,首先你这个类必须称为那个类的子类。

4.2 子类如何访问父类 private 修饰的成员?

其实本期的所有代码,除了4.1例子之外,不管是父类还是子类的成员变量都是 public 修饰的, 那我们前面学过 private 修饰的成员只能在本类中访问,也就是说如果父类中有 private 修饰的成员,我们也会继承下来,但是无法直接访问,因为权限限定符,他限定的就是你访问的权限,那我们就想访问父类使用 private 修饰的成员怎么办?有一个目前能理解的方法:在父类中写一个公共的获取方法就行,比如 public String getName() { return name; }

4.3 为什么 private 和 protected 不能修饰外部类?

我们要先了解他们的权限:

private:如果使用 private 修饰了外部类,那么这个类将不能在其他类中进行实例化,也就是不能用这个类来创建对象,那么这个类的属性和方法就不能被访问,这个类将毫无意义,所Java直接不允许使用 private 修饰外部类

protected:如果 A 类用了 protected 修饰,那么在不同包中的 B 类要想访问 A 类的话,B 必须为 A 的子类, 但是 B 想继承 A 的前提是 B 可以访问到 A,这里就会发生冲突,继承是为了拥有父类的属性和方法,所以 protected 是用来修饰类的成员的

总结:

也就是说,如果我这个类的属性和方法可以被任何的子类访问,我就用 protected,如果我这个类的属性和方法只能在本类中访问,我就用 private,如果我们不想让这个类被继承,就用 final(后续讲)


5、Java中的继承方式 

Java中支持一个类单继承,也就是一个类继承另一个类

Java中支持多层继承,也就是一个类继承了另一个类,另一个类又继承了另一个类

Java中支持不同类继承同一个类,就是一个父类有多个子类,但子类只有一个父类

Java中不支持多继承,也就是不能一个子类有多个父类!

一般我们不希望出现超过三层的继承关系,继承层次太多,就可能考虑要对代码重构了!


6、final 关键字

这个关键字在前面我们也见过,final简单来说可以修饰变量,成员方法,类,我们下面就来看看修饰他们所不同的表现:

final修饰变量:这个我们在之前说过,修饰了变量或者字段,表示常量,是不能被修改的

final修饰方法:表示方法不能被重写(下期介绍)

final修饰类:表示该类不能被继承:


7、继承与组合

组合就相当于一个东西是由什么零件组装而成的,而继承则是把相同的部分抽取了出来,两个其实都是实现代码复用的效果

  • 继承与对象之间的关系是:is - a:比如猫是动物,狗也是动物,他们都属于动物
  • 组合于对象之间的关系是:has - a:比如主机是由CPU,主板,显卡等组合而成形成主机

这个在我们后续的学习中也会接触,这里先做一个简单了了解即可


 下期预告:【Java SE】多态的详解

【Java SE】继承的详解相关推荐

  1. Java SE MyBatis框架(详解)

    Java SE MyBatis框架 目录 Java SE MyBatis框架 通用框架 1.lib 2.src 2.1.mybatis.xml 2.2.DateBase.properties 2.3. ...

  2. Java SE基础知识详解第[12]期—集合(Set、Collections、Map、集合嵌套)

    写在前面: 每一个不曾起舞的日子,都是对生命的辜负. 希望看到这里的每一个人都能努力学习,不负韶华,成就更好的自己. 以下仅是个人学习过程中的一些想法与感悟,Java知识博大精深,作为初学者,个人能力 ...

  3. Java SE基础知识详解第[13]期—不可变集合、Stream流、异常

    写在前面: 每一个不曾起舞的日子,都是对生命的辜负. 希望看到这里的每一个人都能努力学习,不负韶华,成就更好的自己. 以下仅是个人学习过程中的一些想法与感悟,Java知识博大精深,作为初学者,个人能力 ...

  4. Java SE基础知识详解第[18]期—网络编程(通信)

    写在前面: 每一个不曾起舞的日子,都是对生命的辜负. 希望看到这里的每一个人都能努力学习,不负韶华,成就更好的自己. 以下仅是个人学习过程中的一些想法与感悟,Java知识博大精深,作为初学者,个人能力 ...

  5. java的继承实例_java教程之java继承示例详解

    这篇文章主要介绍了java继承示例详解,需要的朋友可以参考下 什么是继承(extends)? 继承是:新定义的类是从已有的类中获取属性和方法的现象. 这个已有的类叫做父类, 从这个父类获取属性和方法的 ...

  6. Java单元测试之JUnit4详解

    2019独角兽企业重金招聘Python工程师标准>>> Java单元测试之JUnit4详解 与JUnit3不同,JUnit4通过注解的方式来识别测试方法.目前支持的主要注解有: @B ...

  7. php中 继承中的概念,JavaScript_JavaScript中的继承方式详解,js继承的概念 js里常用的如下 - phpStudy...

    JavaScript中的继承方式详解 js继承的概念 js里常用的如下两种继承方式: 原型链继承(对象间的继承) 类式继承(构造函数间的继承) 由于js不像java那样是真正面向对象的语言,js是基于 ...

  8. 你真的弄明白了吗?Java并发之AQS详解

    你真的弄明白了吗?Java并发之AQS详解 带着问题阅读 1.什么是AQS,它有什么作用,核心思想是什么 2.AQS中的独占锁和共享锁原理是什么,AQS提供的锁机制是公平锁还是非公平锁 3.AQS在J ...

  9. java定时任务框架elasticjob详解

    这篇文章主要介绍了java定时任务框架elasticjob详解,Elastic-Job是ddframe中dd-job的作业模块中分离出来的分布式弹性作业框架.该项目基于成熟的开源产品Quartz和Zo ...

  10. Java RMI远程方法调用详解

    Java RMI远程方法调用详解     [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/51992182 一.Java R ...

最新文章

  1. 给一份Webservice接口通用实现!!
  2. jquery鼠标滑过展示图片时显示详情
  3. 7篇必读ACM MM 2019论文:图神经网络+多媒体
  4. 深度学习时代的数据科学和自然语言处理
  5. c++ 利用boost 实现文件操作
  6. JavaScript 所有数据类型
  7. eclipse远程调试tomcat
  8. 如何看待不会写代码的架构师?
  9. Javascript 获取验证码60秒倒计
  10. OpenCV-风景—天空滤镜
  11. 关于fineui中在gird中插入按钮的知识
  12. c语言上机南开100题,南开100题上机c语言
  13. Java 的package 機制 王森
  14. 将Excel数据导入Matlab+Matlab二次曲线拟合
  15. wxpy 建群 err_code: 1 err_msg:
  16. eyoumailserver邮箱服务器与foxmail 邮箱客户端的使用和安装
  17. css3的弹性盒子模型,css3弹性盒子模型——回顾。
  18. 燕教授助力公益,已种下60000棵树,修复荒漠78万平方米
  19. 赛迪中国ECM市场报告解读二:鸿翼等国内厂商正在逐步取代跨国企业
  20. 【李开复】给中国学生的第一封信——从诚信谈起 (一)

热门文章

  1. 初识C++(2)——引用
  2. 模糊定位系统画册折页
  3. 3.10【HarmonyOS鸿蒙开发】组件DatePicker
  4. 基于各向异性GGF与自适应PCNN的NSST域图像融合
  5. 阿里面试官用HashMap把我问倒了
  6. List集合一次删除多个元素
  7. PTA团队天梯赛║L1-024 后天
  8. Linux各种cpu外设接口驱动框架
  9. GEE:变化检测算法介绍,和代码(Landtrendr,Bfast,CCDC,CODED,多时间特征叠加的简图分类方法,CUSUM)遥感时间序列
  10. 2020 阿里巴巴面试题 01 附带答案!