当前位置: 首页 > news >正文

Java零基础笔记08(Java编程核心:面向对象编程高级 {继承、多态})

1.继承

         Java中提供了一个关键字extends,用这个关键字,可以让一个类和另一个类建立起父子关系。

子类能继承啥?

● 子类能继承父类的非私有成员(成员变量、成员方法) 继承后对象的创建

● 子类的对象是由子类、父类共同完成的。 

注意: 

        子类对象其实是由子类和父类多张设计图共同创建出来的对象,所以子类对象是完整的

1.1  权限修饰符

        就是用来限制类中的成员 ( 成员变量,  成员方法,  构造器 ) 能够被访问的范围

修饰符		同类	同包		不同包的子类	不同包的非子类	通俗解释
public		✅		✅			✅			✅				完全开放,像公共广场
protected	✅		✅			✅			❌				家族共享,像家族遗产
默认		✅		✅			❌			❌				小区内部,像小区公共设施
private		✅		❌			❌			❌				完全私有,像自家卧室

1.2  继承的特点

1.2.1  单继承和多层继承

public class Test {public static void main(String[] args) {// 目标:继承的注意事项:继承的特点。}
}// 1. java的类只能是单继承的,不支持多继承,支持多层继承
class A {
}class B extends A {
}class C extends B {
}

为什么Java不支持多继承

1.2.2  Java中的祖宗类:Object

● Java中所有类,要么直接继承了Object,要么默认继承了Object,要么间接继承Object。

● 因此,Object是所有类的祖宗类。

1.2.3  继承后子类访问成员的特点:  就近原则

  1. 在子类方法中访问其他成员(成员变量、成员方法),是依照就近原则的。先子类局部范围找,然后子类成员范围找,然后父类成员范围找,如果父类范围还没有找到则报错。

  2. 如果子父类中,出现了重名的成员,会优先使用子类的,如果此时一定要在子类中使用父类的怎么办?可以通过super关键字,指定访问父类的成员:

// 定义父类 Fu
class Fu {// 定义一个字符串属性 name,并初始化为 "fu的name"String name = "fu的name";// 定义一个方法 run,并打印 "fu类的run方法"public void run() {System.out.println("fu类的run方法");}
}// 定义子类 Zi,继承自父类 Fu
class Zi extends Fu {// 定义一个字符串属性 name,并初始化为 "zi的name"String name = "zi的name";// 定义一个方法 show,展示 name 属性的访问特点public void show() {// 定义一个局部变量 name,并初始化为 "show的name"String name = "show的name";// 打印局部变量 name 的值System.out.println(name); // 输出: show的name// 打印当前对象的 name 属性的值,由于就近原则,输出 Zi 类的 nameSystem.out.println(this.name); // 输出: zi的name// 打印父类的 name 属性的值System.out.println(super.name); // 输出: fu的name}// 重写父类的 run 方法,并打印 "zi类的run方法"public void run() {System.out.println("zi类的run方法");}
}// 定义主类 Test2,包含 main 方法
public class Test2 {public static void main(String[] args) {// 创建 Zi 类的对象 ziZi zi = new Zi();// 调用 Zi 类的 show 方法zi.show();// 调用 Zi 类的 run 方法zi.run(); // 输出: zi类的run方法// 调用父类的 run 方法zi.super.run(); // 输出: fu类的run方法}
}

1.2.4  方法重写

        当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。

重写规范:  声明不变,  重新实现

public class Test {public static void main(String[] args) {// 目标:认识方法重写,再搞清楚场景。Cat cat = new Cat();cat.cry();}
}class Cat extends Animal {// 方法重写:方法名称、形参列表必须一样,这个方法就是方法重写。@Override // 方法重写的校验注解(标志),要求方法名称和形参列表必须与被重写方法一致,否则报错!更安全,可读性好,更优雅!public void cry() {System.out.println("🐱 喵喵喵的叫~~~");}
}class Animal {public void cry() {System.out.println("动物会叫~~~");}
}

方法重写在开发中常见的应用场景:

        子类重写Object类的toString()方法,  以便返回对象的内容

public class Test2 {public static void main(String[] args) {// 目标:方法重写的常见应用场景,子类重写Object的toString方法,以便返回对象的内容。Student s = new Student("赵敏", '女', 25);// System.out.println(s.toString()); // com.itheima.extends5override.Student@b4c966a 所谓的地址System.out.println(s); // com.itheima.extends5override.Student@b4c966a 所谓的地址// 注意1:直接输出对象,默认会调用Object的toString方法(可以省略不写调用toString的代码),返回对象的地址信息// 注意2:输出对象的地址实际上总是没有什么意义的,开发中更希望输出对象的内容信息,所以子类需要重写Object的toString方法。// 以便以后输出对象时,默认调用的是子类重写的toString方法返回对象的内容。}
}class Student {private String name;private char sex;private int age;@Overridepublic String toString() {return "Student{name='" + name + "',sex='" + sex + "',age=" + age + "}";}
}

1.2.5  子类构造器

        子类的全部构造器, 都会先调用父类的构造器, 再执行自己

public static void main(String[] args) {// 目标:认识子类构造器的特点,再看应用场景。// 子类构造器都会先调用父类的无参数构造器,再执行自己的构造器。Zi z = new Zi();
}class Zi extends Fu {public Zi() {System.out.println("子类无参构造器执行了");}
}class Fu {public Fu() {System.out.println("父类无参构造器执行了");}
}


// 父类
// 继承的好处:1.代码复用 2.减少了重复代码。public class People {private String name;private char sex;public People() {}public People(String name, char sex) {this.name = name;this.sex = sex;}public String getName() { return name; }public void setName(String name) { this.name = name; }public char getSex() { return sex; }public void setSex(char sex) { this.sex = sex; }
}// 子类
public class Teacher extends People {private String skill; // 技术。public Teacher(String name, String skill, char sex) {// 子类构造器调用父类构造器的应用场景。// 可以把子类继承自父类这部分的数据也完成初始化赋值。super(name, sex);this.skill = skill;}public String getSkill() {return skill;}
}public class Test2 {public static void main(String[] args) {// 目标:子类构造器调用父类构造器的应用场景。Teacher t = new Teacher( name: "dei", skill: "java、大数据、微服务", sex: 'M');System.out.println(t.getName());System.out.println(t.getSkill());System.out.println(t.getSex());}
}

1.2.6 this (...) 调用兄弟构造器 

public class Test3 {public static void main(String[] args) {// 目标:理解this(...)调用兄弟构造器// 创建对象,存储一个学生的数据。Student s1 = new Student(name: "张无忌", sex: '男', age: 23);System.out.println(s1);Student s2 = new Student(name: "赵敏", sex: '女', age: 19);System.out.println(s2);}
}public class Student {private String name;private char sex;private int age;private String schoolName;public Student() {}public Student(String name, char sex, int age) {// this.name = name;// this.sex = sex;// this.age = age;// this.schoolName = "黑马程序员";// this调用兄弟构造器this(name, sex, age, schoolName: "黑马程序员");}public Student(String name, char sex, int age, String schoolName) {this.name = name;this.sex = sex;this.age = age;this.schoolName = schoolName;}public String getName() {return name;}
}

2.多态

        多态是在继承/实现情况下的一种现象,  表现为:  对象多态  和 行为多态

// Test.java
package com.itheima.polymorphism1;public class Test {public static void main(String[] args) {// 目标:认识多态的代码。// 1. 对象多态,行为多态。Animal a1 = new Wolf();a1.run(); // 方法:编译看左边,运行看右边System.out.println(a1.name); // 成员变量:编译看左边,运行看左边Animal a2 = new Tortoise();a2.run(); // 方法:编译看左边,运行看右边System.out.println(a2.name); // 成员变量:编译看左边,运行也看左边}
}// Animal.java
package com.itheima.polymorphism1;public class Animal {String name = "动物";public void run() {System.out.println("动物会跑~~~");}
}// Wolf.java
package com.itheima.polymorphism1;public class Wolf extends Animal {String name = "狼";@Overridepublic void run() {System.out.println("奔跑的狼~~~");}
}// Tortoise.java
public class Tortoise extends Animal {String name = "乌龟";@Overridepublic void run() {System.out.println("乌龟跑的贼慢~~~");}
}

2.1  多态的好处

        在多态形态下,  右边对象是解耦合的,  更便于扩展和维护

// Test.java
public class Test {public static void main(String[] args) {Animal a1 = new Tortoise();a1.run();Wolf w = new Wolf();go(w);Tortoise t = new Tortoise();go(t);}// 宠物游戏:所有动物都可以送给这个方法开始跑步。// 多态的好处2:父类类型的变量作为参数,可以接收一个子类对象public static void go(Animal a) {System.out.println("开始。。。");a.run();}
}// Wolf.java
package com.itheima.polymorphism2;public class Wolf extends Animal {String name = "狼";@Overridepublic void run() {System.out.println("奔跑的狼~~~");}
}// Tortoise.java
// 假设Tortoise类和Wolf类在同一个包中,或者已经正确导入
public class Tortoise extends Animal {String name = "乌龟";@Overridepublic void run() {System.out.println("乌龟跑的贼慢~~~");}
}// Animal.java
// 假设Animal类和Wolf类在同一个包中,或者已经正确导入
public class Animal {String name = "动物";public void run() {System.out.println("动物会跑~~~");}
}

多态下会产生的一个问题, 怎么解决?

        多态性下不能使用子类的独有功能 ( 可以在多态下的类型转换解决 )

2.2  多态下的类型转换

public static void go(Animal a){System.out.println("开始。。。");a.run();// a.shrinkHead(); // 报错,多态下不能调用子类独有功能。// Java建议强制转换前,应该判断对象的真实类型,再进行强制类型转换。if(a instanceof Wolf){Wolf w1 = (Wolf) a;w1.eatSheep();}else if(a instanceof Tortoise){Tortoise t1 = (Tortoise) a;t1.run();}
}
http://www.dtcms.com/a/270688.html

相关文章:

  • 【macOS】【Swift】【RTF】黑色文字在macOS深色外观下看不清的解决方法
  • yolo8实现目标检测
  • springMVC05-异常处理器
  • HashMap源码分析:put与get方法详解
  • 【拓扑空间】示例及详解1
  • sqlplus表结构查询
  • 高效集成-C#全能打印报表设计器诞生记
  • Android-重学kotlin(协程源码第一阶段)新学习总结
  • mongodb: cannot import name ‘_check_name‘ from ‘pymongo.database‘
  • 池化思想-Mysql异步连接池
  • 教育行业可以采用Html5全链路对视频进行加密?有什么优势?
  • 高通 QCS6490PI 集群架构支撑 DeepSeek 模型稳定运行的技术实现
  • upload-labs靶场通关详解:第19关 条件竞争(二)
  • Java-----韩顺平单例设计模式学习笔记
  • java项目maven编译的时候报错:Fatal error compiling: 无效的标记: --release
  • 【计算机组成原理——知识点总结】-(总线与输入输出设备)-学习笔记总结-复习用
  • Caffeine的tokenCache与Spring的CaffeineCacheManager缓存区别
  • uniapp,Anroid10+版本如何保存图片并删除
  • 缓存三大问题详解与工业级解决方案
  • 视频音频转换器V!P版(安卓)安装就解锁V!P!永久免费使用!
  • 【RK3568+PG2L50H开发板实验例程】FPGA部分 | DDR3 读写实验例程
  • 创客匠人:在 IP 变现浪潮中,坚守知识变现的本质
  • 飞算AI-idea强大的AI工具
  • 二分查找篇——在排序数组中查找元素的第一个和最后一个位置【LeetCode】
  • 如何把一个多行的RAS key放到环境变量中?
  • 最新全开源礼品代发系统源码/电商快递代发/一件代发系统
  • 红宝书单词学习笔记 list 26-50
  • 71、【OS】【Nuttx】【启动】启动函数分析
  • 股权结构解析
  • 首批 | 云轴科技ZStack加入施耐德电气技术本地化创新生态