【Java语言】学习笔记-08面向对象【中级】继承的本质分析、快速入门、方法重写、Super关键字的基本语法和使用等细节详解(中)
本篇文章涉及内容:封装、super关键字
跟着一位很厉害的老师学完了java基础,现开始进行javaSE复盘总结知识点,希望可以给java基础薄弱的友友提供一点参考,一起学习Java初级知识,共同进步,打好底层逻辑基础,爱上Java编程❤️❤️❤️
(本文章中知识点如有不同的见解,欢迎评论区留言)
tips: 本章在整个Java基础的知识点处于一个比较重要的地位,其中包括封装、继承、多态,属于我们java的一大特色,但同时这部分的内容比较多和琐碎,希望友友们反复观看笔记加深印象
本章内容较多分为上中下三篇,这里是中篇
【上篇】地址: 第 8 章、面向对象编程【中级】包、访问修饰符、封装
目录
- 4、继承
- 4.1、认识
- 4.1.1、为什么继承
- 4.1.2、继承示意图
- 4.2、快速入门
- 4.3、继承细节Detail
- 4.3.1、Detail 01
- 4.3.2、Detail 02
- 4.3.3、Detail 03
- 4.3.4、Detail 04
- 4.4、继承的本质分析(*)
- 4.5、小练习(有点意思比较绕🤔)
- 5、super关键字
- 5.1、super基础
- 5.2、super细节(Detail)
- 5.2.1、细节1
- 5.2.2、细节2
- 5.3、super 和 this 的区别
- 6、overwrite(方法重写)
- 6.1、认识
- 6.2、override细节Detial
- 6.3、overload和override区别(*)
- 恭喜🎉你打败了76%的人
- 继续努力
4、继承
4.1、认识
4.1.1、为什么继承
试想有一个Teacher类和一个Student类中都有name、age、gender等属性和一些相同的方法,每次都写就会占用时间和程序空间;
这时我们不如创建一个Person类,里面存放一些大家都有的属性和方法,利用继承 达到子类中可以使用这些属性和方法的作用。
- 代码的复用性提高了
- 代码的扩展性和维护性提高了
继承(代码复用性)
(有两个类(pupil和graduate)属性和方法大部分相同,代码复用性差)
4.1.2、继承示意图
4.2、快速入门
- tips : 如果担心名字是关键字,那么就加个横线improve_ (package)
代码实现
- Student类
package com.fhsdu.extend_.improve_;
//父类,是Pupil,Graduate的
public class Student {
public String name;
public int age;
private double score;
public void setScore(double score) {
this.score = score;
}
public void showInfo() {
System.out.println("学生姓名=" + name + "年龄 " +
age + "成绩" + score);
}
}
- Pupil类
package com.fhsdu.extend_;
//小学生 -》模拟小学生考试的情况
public class Pupil {
public String name;
public int age;
private double score;
public void setScore(double score) {
this.score = score;
}
public void testing(){
System.out.println("正在考小学数学");
}
public void showInfo(){
System.out.println("小学生姓名=" + name + "年龄 " +
age + "成绩" + score);
}
}
- Graduate类
package com.fhsdu.extend_.improve_;
public class Graduate extends Student{
public void testing(){//和Pupil不一样
System.out.println("大学生" + name +" 正在考大学数学。。。");
}
}
- 主方法main
package com.fhsdu.extend_.improve_;
public class Extends01 {
public static void main(String[] args) {
com.fhsdu.extend_.improve_.Pupil pupil = new Pupil();
pupil.name = "开心超人";
pupil.age = 10;
pupil.setScore(60);
pupil.testing();
pupil.showInfo();
System.out.println("============");
com.fhsdu.extend_.improve_.Graduate graduate = new Graduate();
graduate.name = "大大怪";
graduate.age = 20;
graduate.setScore(100);
graduate.testing();
graduate.showInfo();
}
}
4.3、继承细节Detail
4.3.1、Detail 01
代码实现
默认的你可以换个角度看,这个子类是不是和父类同包,默认的是不是同包下可以访问(解释了子类访问默认属性和方法)
package com.fhsdu.extend_;
public class Base {//父类
public int n1 = 100;
protected int n2 = 200;
int n3 = 300;
private int n4 = 400;
public Base(){//无参构造器
System.out.println("base()....");
}
//父类提供一个public的方法
public int getN4() {
return n4;
}
public void test100(){
System.out.println("test100");
}
protected void test200(){
System.out.println("test200");
}
void test300(){
System.out.println("test300");
}
private void test400(){
System.out.println("test400");
}
//相当于中转,使用call调用私有方法test400
public void callTest400(){
test400();
}
}
package com.fhsdu.extend_;
public class Sub extends Base{//子类
public Sub(){
System.out.println("sub()...");
}
public void sayOk(){//子类方法
//非私有的属性和方法可以在子类直接访问
//但是私有的属性和方法不能再子类直接访问
System.out.println(n1 + " " + n2 +
" " + n3);
test100();
test200();
test300();
//test400();错误
System.out.println("n4=" + getN4());
//test400
callTest400();
}
}
- 测试
package com.fhsdu.extend_;
public class ExtendsDetail {
public static void main(String[] args) {
Sub sub = new Sub();
sub.sayOk();
}
}
4.3.2、Detail 02
public Sub(){//子类无参构造器
//super();//默认调用父类无参构造器
System.out.println(“子类Sub()构造器被调用”);
}
- 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器
super()
当父类构造器创建有参构造器时 , 无参构造器将被覆盖,则子类的无参构造器不生效,会报错
4.3.3、Detail 03
- 调用父类的无参构造器:1、super(); 2、什么都不写,默认调用无参
- 必须调用一个父类的构造器,带参数的: super(“str1”,n2,…)->加上参数
- super使用时必须放在子类构造器的第一条
- super() 和 this() 都只能放在构造器第一条 , 因此两个方法不能共存在一个构造器中.
——> this指的是子类的方法
4.3.4、Detail 04
- java所有类都是Object的子类 ➡️ control + h 查看类属
- 父类构造器的调用不限于直接父类 ! 将一直往上追溯直到Object类(顶级父类)
- 子类最多只能继承一个父类(指直接继承) 即java中是 单继承机制.
- 思考: 如何让A类继承B类和C类?
a 继承 b ,再让 b 继承 c
- 不能滥用继承 , 子类和父类之间必须满足is - a的逻辑关系
4.4、继承的本质分析(*)
代码实现
package com.fhsdu.extend_;
public class ExtendsTheory {
/*
*讲解继承的本质
* */
public static void main(String[] args) {
Son son = new Son();//内存的布局
//?-> 这时请大家注意,要按照查找关系来返回信息
//(1) 首先看子类是否有该属性
//(2) 如果子类有这个属性,并且可以访问,则返回信息
//(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)
//(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object... System.out.println(son.name);//返回就是大头儿子
//System.out.println(son.age);//返回的就是 39
//System.out.println(son.getAge());//返回的就是 39
System.out.println(son.hobby);//返回的就是旅游
}
}
class GrandPa { //爷类
String name = "大头爷爷";
String hobby = "旅游";
}
class Father extends GrandPa {//父类
String name = "大头爸爸";
private int age = 39;
public int getAge() {
return age;
}
}
class Son extends Father { //子类
String name = "大头儿子";
}
- 如果father类中age是私有的,grandpa中的age是共有的,那么调用 son.age也会报错 ,因为到father中就会返回,被覆盖了,如果father有不会去上面找
4.5、小练习(有点意思比较绕🤔)
答案 : a , b name, b 先执行b的带参方法 ->B() 中有this就不会出现默认的super()方法
答案 (输出):
1、我是A类
2、hahah, 我是B类的有参构造
3、我是c类的有参构造
4、我是c类的无参构造
(思考调用流程)
5、super关键字
5.1、super基础
- 与之前讲的相同,私有的属性和方法都不能调用 , 可以使用第三方(共有)转化super.属性/方法
- super() , 必须在构造器中使用并且在第一条 , 方法中不能使用
5.2、super细节(Detail)
5.2.1、细节1
5.2.2、细节2
就近原则
当然也遵循访问权限的相关规则
5.3、super 和 this 的区别
6、overwrite(方法重写)
介绍:方法覆盖就是子类中有一个方法,和父类的某个方法名称、返回类型、参数一样,我们就说子类的方法覆盖了父类的方法
6.1、认识
6.2、override细节Detial
- 重写时子类的返回值类型必须是父类的子类,方法名相同,参数相同(或者返回值相同)
- 子类重写的方法,返回值类型是父类的父类就会报错
子类
父类
如果父类中返回对象AAA(AAA和BBB是同一级的),那么子类中的重写方法返回值是BBB也是可以的。 同类
子类的访问权限不能缩小父类的访问权限
- 访问权限:
- public ➡️ protected ➡️ 默认 ➡️ private
6.3、overload和override区别(*)
名称 | 发生范围 | 方法名 | 形参列表 | 返回类型 | 修饰符 |
---|---|---|---|---|---|
重载(overload) | 本类 | 必须一样 | 类型,个数或者顺序至少有一个不同 | 无要求 | 无要求 |
重写(override) | 父子类 | 必须一样 | 相同 | 子类重写的方法,返回的类型和父类返回的类型一致,或者是其子类 | 子类方法不能缩小父类方法的访问范围 |