09_方法重写丶多态丶抽象类
Day09笔记
课程内容
1、继承中成员方法的关系和方法的重写
2、final
3、多态
4、抽象类
5、接口
继承剩余内容
继承中成员方法的关系
1、在子父类中,有不同名称的成员方法
在子类中,可以直接访问父类中定义的成员方法,也可以访问子类中定义的成员方法
2、在子父类中,有相同声明的方法(方法的返回值类型、方法名称、参数列表)
称为:方法重写(Override)
在子父类中,出现了一模一样的方法声明,但是方法的实现却各不相同
作用:在子类中,【如果】不想改变父类中定义过的方法声明,但是还想改变这个方法的实现内容。
3、方法重载和方法重写的比较:
重载:在同一个类中,方法名相同,参数列表不同,与返回值类型无关
重写:在子父类中,方法名相同,参数列表也相同,与返回值类型有关(相同)
4、方法重写的说明:
1、别称:覆写、覆盖、override
2、注解:@Override
作用:检查当前的方法是否在重写父类中的某个方法
3、在子类中重写父类的方法,只是在改变父类方法的内容,使用的还是父类中的方法定义:子类中被重写的这个方法,所属关系,属于父类的,只是子类重写了内容而已。
4、如果在子类中,还想访问父类的方法,使用super.方法名称();
代码示例
class Demo01_方法的重写 {
public static void main(String[] args) {
DayOne d = new DayOne();
d.singRedSong();
d.paoNiu();
System.out.println("--------");
d.test();
}
}
class DoubleRiver {
public void singRedSong() {
System.out.println("小小竹筏江中游");
}
public void paoNiu() {
System.out.println("通过唱歌搞定林夕合鸟女士");
}
}
class DayOne extends DoubleRiver {
@Override
public void paoNiu() {
System.out.println("霸王硬上弓");
}
public void test() {
this.paoNiu();
super.paoNiu();
}
}
重写的注意事项
1、私有的方法不能被重写
父类中的私有方法,在子类中根本就看不到,子类也继承不了父类中的私有成员,也就没有办法重写
在子类中,仍然可以定义一个和父类私有方法同名的方法,但是这不是对父类方法的重写,而是在子类中心定义了一个方法
2、方法在重写的时候,权限不能越来越小
工程上的原因:将来面向父类、面向接口编程,有这些方法的,代码运行的时候是运行子类的方法,方法没有了
记忆:子类重写父类,必须功能越来越强,权限不能越来越小
代码示例
class Demo02_重写的注意事项 {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
class Fu {
public void test1() {
System.out.println("Fu111");
}
private void test2() {
System.out.println("Fu222");
}
public void test3() {
System.out.println("Fu333");
}
}
class Zi extends Fu {
@Override
public void test1() {
System.out.println("Zi111");
}
/*@Override//私有方法不能重写
public void test2() {
System.out.println("Zi222");
}
@Override//权限不能越写越小
private void test3() {
System.out.println("Zi333");
}*/
}
final关键字
概述
1、final:最后的、最终的、不能改变的
2、Java中,可以修饰类、方法、变量(局部变量和成员变量)
3、final修饰类:
该类不能被继承,类中的任何内容都无法改变,类中的成员方法,都不能被重写了
4、final修饰方法:
该方法不能被重写
5、final修饰变量:
变量就变成了常量,只能赋值一次
代码示例1
class Demo03_final修饰类 {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
final class DoubleRiver {
public void singRedSong() {
System.out.println("小小竹筏江中游");
}
public void paoNiu() {
System.out.println("通过唱歌搞定林夕合鸟女士");
}
}
//编译报错,final修饰之后,不能被继承
class DayOne extends DoubleRiver {
}
代码示例2
class Demo04_final修饰方法 {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
class DoubleRiver {
public void singRedSong() {
System.out.println("小小竹筏江中游");
}
public final void paoNiu() {
System.out.println("通过唱歌搞定");
}
}
class DayOne extends DoubleRiver {
//编译报错,因为父类中的paoNiu是final的,不能被重写
public void paoNiu() {
}
public void singRedSong() {
}
}
代码示例3
class Demo05_final修饰变量 {
public static void main(String[] args) {
final int a = 10;
System.out.println(a);
a = 20;//编译报错,因为a是最终变量,只能赋值一次
System.out.println(a);
}
}
final修饰局部变量和成员变量的注意事项
1、final修饰局部变量的注意事项:
final修饰哪个变量,哪个变量不能改变
final修饰基本数据类型,变量中的值不能改变
final修饰引用数据类型,变量中的地址值不能改变
2、final修饰成员变量的注意事项:
final修饰成员变量,需要注意初始化时机,原因:
成员变量有很多的初始化步骤,所以有可能在我们没有手动给变量赋值之前,变量就已经赋值很多次了
时机:
在构造方法结束之前,必须给final修饰的成员变量赋值
final修饰的成员变量,没有默认初始化
结论:final修饰的成员变量,只能有显式初始化、构造方法初始化
代码示例1
class Demo06_final修饰局部变量 {
public static void main(String[] args) {
Person p = new Person();
p.name = "zhangsan";
p.name = "lisi";
final Person p1 = new Person();
p1.name = "zhangsan";
System.out.println(p1.name);
p1.name = "lisi";
System.out.println(p1.name);
//p1 = new Person();//编译报错,因为p1是最终变量,不能修改内容
}
}
class Person {
String name;
}
代码示例2
class Demo07_final修饰成员变量 {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
class Person {
//final String name;//编译报错,没有在有限的两次机会中初始化该变量
final int age = 6;
final String sex;
public Person() {
sex = "m";
}
/*public Person(int age) {
}*///编译报错,如果调用该构造方法,没有初始化sex属性
/*public void setSex(String sex) {
this.sex = sex;
}*///编译报错,因为已经确保最终变量在创建对象时,已经分配值
}
多态
多态的概述
1、多态:事物的多种状态,polymorphic
对象的多态性:同一个对象,可以有不同的名称,有不同的类型的引用指向它
本质:同一个对象有不同的名称和描述
类型的多态性:同一个类型的引用,将来可以指向不同的子类对象
本质:同一个名称可以描述多种具体的事物
2、多态的前提:
1、要有子父类(接口和实现类)的继承关系(实现关系)
2、要有方法的重写
3、父类的引用指向子类的对象
代码示例
class Demo08_多态概述 {
public static void main(String[] args) {
Man m = new Man();
m.speak();
Person p = new Man();
p.speak();
}
}
class Person {
public void speak() {
System.out.println("我是人");
}
}
class Man extends Person {
@Override
public void speak() {
System.out.println("我是大男人");
}
}
在多态中成员变量的访问特点
1、编译看左边,运行看左边
2、在编译阶段,使用父类的引用访问某个成员变量,检查在引用所属的类型中(赋值符号左边的类型)是否有该变量的定义,如果有,编译成功,如果没有就编译失败。
3、在运行阶段,使用父类的引用访问某个成员变量,访问的还是引用所属的类中(赋值符号左边的类型)对该变量的赋值
代码示例
class Demo09_多态中成员变量的访问特点 {
public static void main(String[] args) {
Person p = new Man();
System.out.println(p.name);
}
}
class Person {
//String name = "张三";
}
class Man extends Person {
String name = "张三丰";
}
在多态中成员方法的访问特点
1、编译看左边,运行看右边
2、使用父类的引用访问了某个成员方法,在编译阶段,检查引用所属的类型中(赋值符号左边的类型),是否有该方法的定义,如果有,编译成功,如果没有,就编译失败
3、使用父类的引用访问某个成员方法,在运行阶段,运行的内容是对象所属的类型(赋值符号右边的类型)重写过的内容。
代码示例
class Demo10_多态中成员方法的访问特点 {
public static void main(String[] args) {
Person p = new Man();
p.speak();
Person p1 = new Woman();
p1.speak();
}
}
class Person {
public void speak() {
System.out.println("我叫张三");
}
}
class Man extends Person {
public void speak() {
System.out.println("我叫张三丰");
}
}
class Woman extends Person {
public void speak() {
System.out.println("我是张小凤");
}
}
多态中静态方法的访问特点
1、编译看左边,运行看左边
2、编译时,要看【=】左边的引用所属的类型(父类)是否有该方法的定义,如果有就编译成功,如果没有,就编译失败
3、运行时,要看【=】右边的引用所属的类型(父类)究竟是如何实现该方法的,运行的是父类中方法的实现
4、静态理解总结:
静态变量:存储在类的字节码中,被所有该类对象共享,这个变量的值不会随着对象的不同,而又不同的值,都是相同的值,称为“静态”
静态方法:只会引用所属的父类,决定运行内容,不会随着对象的不同而运行不同的方法实现,称为“静态方法”
代码示例
class Demo11_多态中静态方法的访问特点 {
public static void main(String[] args) {
Person p = new Man();
//父类中定义了speak这个方法,如果是子类重写了这个方法,那么在父类调用这个方法的时候,就应该走子类的实现
//而运行结果是父类的内容,因此说明子类没有重写这个方法,而是新定义了一个方法
p.speak();
Person p1 = new Woman();
p1.speak();
}
}
class Person {
public static void speak() {
System.out.println("我是张三");
}
}
class Man extends Person {
//@Override //静态方法没有重写的概念
public static void speak() {
System.out.println("我是张三丰");
}
}
class Woman extends Person {
public static void speak() {
System.out.println("我是张小凤");
}
}
超人案例
代码示例
class Demo12_超人案例 {
public static void main(String[] args) {
Man m = new SuperMan();
System.out.println(m.name);
m.谈生意();
//向下转型:恢复原本的访问范围
SuperMan sm = (SuperMan)m;
sm.fly();
}
}
class Man {
String name = "Mike";
public void 谈生意() {
System.out.println("谈一谈不同的小生意");
}
}
class SuperMan extends Man {
String name = "Spider";
@Override
public void 谈生意() {
System.out.println("谈的是几个亿的大单子");
}
public void fly() {
System.out.println("到处飞着救人");
}
}
多态的内存理解
引用类型的向上向下转型
1、向上转型:多态的体现
父类的引用指向了子类的对象
以前:子类的引用 = 子类的对象
现在:父类的引用 = 子类的对象
本质:从概念上说,把概念扩大了,但是从功能和数据说,把访问范围缩小了
2、向下转型:
本质:把曾经扩大的概念进行恢复;把曾经缩小的访问范围恢复
前提:曾经向上转型过
格式:
子类类型 子类引用名称 = (子类类型)父类引用名称;
多态的好处
1、提高了代码的可扩展性
同一个类型的引用,可以有不同的子类对象作为实现
2、在方法的形式参数中,使用父类类型的引用,将来在调用方法的时候,传入的实际参数可以是这个父类的所有子类的对象。
3、不在方法的形式参数中,使用父类类型的引用,指向的对象,来源非常广泛的(不仅仅是new出来的),可以是通过反射的方式获取的,可以是通过文件读取获取的,可以是网络中传过来的,数据库中读取的。以上方式,都是程序员在写代码的时候,不知道对象具体的子类类型,仍然可以使用父类的引用指向他们,将来根据具体子类的不同,仍然可以运行不同的代码。
代码示例
import java.io.BufferedReader;
import java.io.FileReader;
class Demo13_榨汁机案例 {
public static void main(String[] args) throws Exception {
JuiceMachine jm = new JuiceMachine();
/*Apple a = new Apple();
jm.makeJuice(a);
Orange o = new Orange();
jm.makeJuice(o);*/
BufferedReader br = new BufferedReader(new FileReader("config.txt"));
String className = br.readLine();
Class c = Class.forName(className);
//Object也是最顶层的父类,指向了我们不知道的具体类型的子类对象
Object obj = c.newInstance();
//父类的Fruit类型的对象,指向了我们不知道具体类型的子类对象
Fruit f = (Fruit)obj;
jm.makeJuice(f);
}
}
class JuiceMachine {
public void makeJuice(Fruit f) {//Fruit f = new Orange();
f.flow();
}
}
class Fruit {
public void flow() {
}
}
class Apple extends Fruit {
public void flow() {
System.out.println("流出苹果汁");
}
}
class Orange extends Fruit {
public void flow() {
System.out.println("流出橘子汁");
}
}
class WaterMelon extends Fruit {
public void flow() {
System.out.println("流出西瓜汁");
}
}
抽象类
抽象方法
1、抽象:抽取像的,相同的相似的内容出来
2、抽象方法:
在子类中,对同一个方法,不同的子类有不同的实现,不同子类中的这些方法,就只有方法声明是相同的,所以把方法名称抽取到父类中,就是抽象方法。
抽象方法:就是只有方法声明,没有方法实现的方法
3、定义格式:
1、没有方法体,只有方法实现,连方法体的大括号都没有,通过分号结束方法
2、在方法声明上,需要加一个abstract关键字来说明这个方法是抽象方法
代码示例
class Demo14_抽象方法 {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
class Employee {
public abstract void work();
}
class Coder extends Employee {
public void work() {
System.out.println("敲代码");
}
}
class Tester extends Employee {
public void work() {
System.out.println("软件测试");
}
}
抽象类
1、可以定义抽象方法的类,就是抽象类
2、定义格式:
abstract class 类名 {
抽象方法;
}
代码示例
class Demo15_抽象类 {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
abstract class Employee {
public abstract void work();
}
class Coder extends Employee {
public void work() {
System.out.println("敲代码");
}
}
class Tester extends Employee {
public void work() {
System.out.println("软件测试");
}
}
抽象类的特点
1、抽象类和抽象方法都需要使用abstract关键字声明
abstract class 类名 {}
public abstract 返回值类型 方法名称() {}
2、抽象类和抽象方法的关系:
1、抽象类中,未必有抽象方法
2、抽象方法所在的类,一定是抽象类
3、抽象类不能实例化(创建对象)
抽象类中有抽象方法,如果能创建对象,就会调用没有意义的方法
只能定义子类,重写(实现)抽象方法之后,使用子类来创建对象
4、抽象类的子类:
1、如果子类没有把父类中的所有抽奖方法都重写,那么这个子类就还是一个抽象类
2、如果子类重写了父类中所有的抽象方法,那么子类就变成了一个具体类。
代码示例
class Demo16_抽象类的特点 {
public static void main(String[] args) {
Coder c = new Coder();
}
}
abstract class Employee {
public void test() {}
public abstract void test2();
}
class Coder extends Employee {
}
抽象类中成员的特点
1、成员变量的特点:
既可以是变量、也可以是常量
但是不能被抽象
2、构造方法的特点:
抽象类中,有构造方法
用于子类创建对象的时候,要访问父类的构造方法
一个类中是否需要定义构造方法,不是取决于这个类是否可以创建对象,而是取决于该类是否可以定义成员变量
3、成员方法的特点:
可以是抽象方法:强制让子类重写这个抽象方法
也可以是非抽象方法:用于给子类继承
代码示例
class Demo17_抽象类中成员的特点 {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
abstract class Employee {
String name;
final int age = 65;
}
员工类案例完善
代码示例
class Demo18_员工类案例 {
/*
定义程序员类和项目经理类
程序员类:属性(姓名、工号、工资)、方法(工作:敲代码)
项目经理类:属性(姓名、工号、工资、奖金)、方法(工作:项目进度控制
*/
public static void main(String[] args) {
//Coder c = new Coder("李白", "lb666", 20000.0);
//抽象父类的引用,指向具体子类的对象:抽象类的多态
Employee e1 = new Coder("李白", "lb666", 20000.0);
System.out.println(e1.getName() + "..." + e1.getId() + "..." + e1.getSalary());
e1.work();
//Manager m = new Manager("秦始皇", "qsh888", 0, 999999999);
Employee e2 = new Manager("秦始皇", "qsh888", 0, 999999999);
//编译报错,因为在父类Employee中没有getBonus这个方法
//System.out.println(e2.getName() + "..." + e2.getId() + "..." + e2.getSalary() + "..." + e2.getBonus());
System.out.println(e2.getName() + "..." + e2.getId() + "..." + e2.getSalary());
e2.work();
}
}
abstract class Employee {
private String name;
private String id;
private double salary;
public Employee() {}
public Employee(String name, String id, double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setSalary(double salary) {
this.salary = salary;
}
public double getSalary() {
return salary;
}
public abstract void work();
}
class Coder extends Employee {
public Coder() {}
public Coder(String name, String id, double salary) {
super(name, id, salary);
}
public void work() {
System.out.println("敲代码");
}
}
class Manager extends Employee {
private int bonus;
public Manager() {}
public Manager(String name, String id, double salary, int bonus) {
super(name, id, salary);
this.bonus = bonus;
}
public void setBonus(int bonus) {
this.bonus = bonus;
}
public int getBonus() {
return bonus;
}
public void work() {
System.out.println("项目进度控制");
}
}
转载于:https://www.cnblogs.com/man-tou/p/10635905.html
09_方法重写丶多态丶抽象类相关推荐
- JavaSE(四)——方法重写、多态、接口
文章目录 1. 方法重写 1.1 定义 1.2 重写的注意事项 1.3 实例 2. final关键字 2.1 定义 2.2 修饰特点 3. 多态 3.1 定义 3.2 多态前提 3.3 成员访问特点 ...
- Java Part1 Day11继承 方法重写 super多态
面向对象 一.内容回顾 封装;将类内部的属性隐藏private在类的内部,通过对外的公共接口(public setxxx getxxx)去操作,切薄数据的安全(合理) 实现过程:1属性私有 2封装方法 ...
- Java SE_封装、继承、object类、super-this关键字、方法重写、多态、instanceof、类型转换
封装 该露的露,该藏的藏 我们程序设计要追求"高内聚,低耦合".高内聚:类的内部数据操作细节自己完成,不允许外部干涉:低耦合:仅暴露少量的方法给外部使用. 封装(数据的隐藏) 通常 ...
- 面向对象1---this、构造方法、方法重载,静态,权限、getter和sett、继承、super、方法重写、多态
面向对象 1.类与对象 面向对象: 类:就是图纸 属性:这一类的共同属性 动作方法:这一类事务共同能执行的功能 对象使用类创建的某一个东西 对象能干什么,完全于类是如何定义的 写代码 类要使用clas ...
- Java笔记013-IDEA、包、访问修饰符、封装、继承、多态、Super、方法重写/覆盖(override)、java的动态绑定机制
目录 面向对象编程(中级部分) IDE(集成开发环境)-IDEA IDEA介绍 IDE(集成开发环境)-Eclipse Eclipse介绍 IDEA的安装 IDEA的基本介绍和使用 创建一个java项 ...
- Java---面向对象编程三大特征【封装、继承、多态】及super关键字、方法重写/覆盖(不定期更新补充)---B站韩顺平老师视频总结
文章目录 三大特征 面向对象编程-封装 封装介绍 封装的理解和好处 封装的实现步骤(三步) 封装的简单案例 封装与构造器 封装的练习 面向对象编程-继承 为什么需要继承 继承基本介绍和示意图 继承的基 ...
- Java面向对象之继承,方法重写,super关键字,员工类系列继承题
在程序中,如果想声明一个类继承另一个类,需要使用extends关键字. 格式: class 子类 extends 父类 {} 继承的好处 1.继承的出现提高了代码的复用性,提高软件开发效率. 2.继承 ...
- 类,多态,抽象类,接口
代码块: 局部代码块: 构造代码块:和构造方法一起执行,并且先于构造方法执行,每new一次 就执行一次 静态代码块:和类一起加载, 并且只执行一次 子类会继承父类中的数据,所有子类初始化之前一定会先初 ...
- 9-java学习-多态、抽象类、接口-案例代码
9-java学习-多态.抽象类.接口-案例代码 一.多态 1.多态:一种事物,在不同时刻所表现出的不同状态. 多态的前提要有继承.没有继承,那么动态就无从谈起 多态要有方法重写,如果没有方法重 ...
最新文章
- Android Camera设置setPreviewCallback实现onPreviewFrame接口实时截取每一帧视频流数据
- VR/AR会是微信后马化腾进军的战场吗
- Load 和 DOMContentLoaded 区别
- tkinter之事件绑定
- Python基础知识(第二天)
- c语言理解参数,c语言中对可变参数列表的简单理解
- Windows下C/C++获取当前系统时间
- 腾讯万亿级 Elasticsearch 内存效率提升技术解密
- java加载自己写的类_java 自定义类加载器从磁盘或网络加载类
- C# 8: 可变结构体中的只读实例成员
- java父类序列化_父类的序列化与 Transient 关键字
- PropertyGrid控件 分类(Category)及属性(Property)排序
- java验证码Kaptcha
- 钱准备好!苹果官方账号泄密:iPhone 12明晚发布有戏
- 301永久重定向实现方式及302重定向(侧重.htaccess)
- NopCommerce(Core)学习目录
- 在excel中批量生成条形码的操作方法?
- 中国未来房价基本走势的分析和预测
- python求一组数的最大值_用python实现在一组数据中,寻找到最大数和最小数并输出最大数和最小数所在的位置...
- Java虚拟机部分知识点