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

阶段二JavaSE进阶阶段之多态、关键字、抽象类 2.3

文章目录

  • 一、面向对象三大特征之多态
    • 1.1 多态的概述
    • 1.2 多态的好处
    • 1.3 多态的注意事项
  • 二、final关键字
    • 2.1 final修饰符的特点
    • 2.2 常量
  • 三、 抽象类
    • 3.1 什么是抽象类
    • 3.2 抽象类的场景和好处
    • 3.3 模板方法设计模式
  • 总结


详细的java学习路径和教程请看我写的另一篇java小白到大牛的快速直通车


一、面向对象三大特征之多态

1.1 多态的概述

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

比如:Teacher和Student都是People的子类,代码可以写成下面的样子
在这里插入图片描述
在这里插入图片描述

1.2 多态的好处

在多态形式下,右边的代码是解耦合的,更便于扩展和维护。

怎么理解这句话呢?比如刚开始p1指向Student对象,run方法执行的就是Student对象的业务;假如p1指向Teaacher对象 ,run方法执行的自然是Teaacher对象的业务
在这里插入图片描述

定义方法时,使用父类类型作为形参,可以接收一切子类对象,扩展行更强,更便利。

public class Test2 {public static void main(String[] args) {Teacher t = new Teacher();go(t);Student s = new Student();go(s);}//参数People p既可以接收Student对象,也能接收Teacher对象。public static void go(People p){	//People p = new Teacher/StudentSystem.out.println("开始------------------------");p.run();System.out.println("结束------------------------");}
}

1.3 多态的注意事项

虽然多态形式下有一些好处,但是也有一些弊端。在多态形式下,不能调用子类特有的方法,比如在Teacher类中多了一个teach方法,在Student类中多了一个study方法,这两个方法在多态形式下是不能直接调用的。
在这里插入图片描述
此时我们需要对p对象进行强转
在这里插入图片描述
如果类型转换错了,就会出现类型转换异常ClassCastException,比如把Teacher类型转换成了Student类型.
在这里插入图片描述
所以多态形式下不能直接调用子类特有方法,但是转型后是可以调用的。这里所说的转型就是把父类变量转换为子类类型。并且为了稳妥起见,防止转换类型出错,我们最好加上判断,格式如下:

//如果p接收的是子类对象
if(父类变量 instance 子类){//则可以将p转换为子类类型子类 变量名 = (子类)父类变量;
}

在这里插入图片描述

二、final关键字

接下来我们学习一个在面向对象编程中偶尔会用到的一个关键字叫final,也是为后面学习抽象类和接口做准备的。

2.1 final修饰符的特点

我们先来认识一下final的特点,final关键字是最终的意思,可以修饰类、修饰方法、修饰变量。

  • final修饰类:该类称为最终类,特点是不能被继承
  • final修饰方法:该方法称之为最终方法,特点是不能被重写。
  • final修饰基本类型变量:该变量只能被赋值一次。
  • final修饰引用类型变量:该变量的地址不可被改变,但地址所指向的内容是可以被改变的

接下来我们分别演示一下,先看final修饰类的特点
在这里插入图片描述
再来演示一下final修饰方法的特点
在这里插入图片描述
再演示一下final修饰变量的特点

  • 情况一
    在这里插入图片描述
  • 情况二
    在这里插入图片描述
  • 情况三
    在这里插入图片描述
    在这里插入图片描述

2.2 常量

在Java中被 static final 修饰的成员变量,称之为常量。

常量通常被用于记录系统的配置信息
接下来我们用代码来演示一下

public class Constant {//常量: 定义一个常量表示学校名称//为了方便在其他类中被访问所以一般还会加上public修饰符//常量命名规范:建议都采用大写字母命名,多个单词之前有_隔开public static final String SCHOOL_NAME = "清华大学";
}
public class FinalDemo2 {public static void main(String[] args) {//由于常量是static的所以,在使用时直接用类名就可以调用System.out.println(Constant.SCHOOL_NAME);System.out.println(Constant.SCHOOL_NAME);System.out.println(Constant.SCHOOL_NAME);System.out.println(Constant.SCHOOL_NAME);System.out.println(Constant.SCHOOL_NAME);System.out.println(Constant.SCHOOL_NAME);System.out.println(Constant.SCHOOL_NAME);}
}

那么当我们想把展示信息从清华大学改成北京大学是,只需要修改Constant中的常量就可以了,这样让我们的代码可读性会提升,也方便我们后期的维护

在程序编译后,常量会“宏替换”,出现常量的地方,全都会被替换为其记住的字面量。把代码反编译后,其实代码是下面的样子

public class FinalDemo2 {public static void main(String[] args) {System.out.println("清华大学");System.out.println("清华大学");System.out.println("清华大学");System.out.println("清华大学");System.out.println("清华大学");System.out.println("清华大学");System.out.println("清华大学");}
}

三、 抽象类

3.1 什么是抽象类

抽象类顾名思义,是一种没有具体的行为或属性的类,在Java中有一个关键字叫abstract,它就是抽象的意思,它可以修饰类也可以修饰方法。

  • 被abstract修饰的类,就是抽象类
  • 被abstract修饰的方法,就是抽象方法(不允许有方法体)

接下来用代码来演示一下抽象类和抽象方法

//abstract修饰类,这个类就是抽象类
public abstract class A{//abstract修饰方法,这个方法就是抽象方法public abstract void test();
}

抽象类的注意事项:

  • 抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类
  • 类该有的成员(成员变量、方法、构造器)抽象类都可以有
// 抽象类
public abstract class A {//成员变量private String name;static String schoolName;//构造方法public A(){}//抽象方法public abstract void test();//实例方法public String getName() {return name;}public void setName(String name) {this.name = name;}
}
  • 抽象类不能被创建对象,仅作为一种特殊的父类,让子类继承并实现
//B类继承抽象A类,必须复写test方法
public class B extends A {@Overridepublic void test() {}
}
  • 一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义为抽象类
    在这里插入图片描述

3.2 抽象类的场景和好处

现在有如下的需求:
某宠物店,需要管理猫和狗的数据。
猫的数据有:名字;行为是:喵喵喵的叫~
狗的数据有:名字;行为是:汪汪汪的叫~

分析需求发现,该案例中猫和狗都有名字这个属性,也都有叫这个行为,所以我们可以将共性的内容抽取成一个父类,Animal类,但是由于猫和狗叫的声音不一样,于是我们在Animal类中将叫的行为写成抽象的。代码如下

public abstract class Animal {private String name;//动物叫的行为:不具体,是抽象的public abstract void shout();public String getName() {return name;}public void setName(String name) {this.name = name;}
}

接着写一个Animal的子类,Dog类。代码如下

public class Dog extends Animal{public void shout(){System.out.println(getName() + "汪汪汪的叫~~");}
}

然后,再写一个Animal的子类,Cat类。代码如下

public class Cat extends Animal{public void shout(){System.out.println(getName() + "喵喵喵的叫~~");}
}

最后,再写一个测试类,Test类。

public class Test2 {public static void main(String[] args) {// 利用多态来创建对象Animal a = new Dog();a.cry();	//这时执行的是Dog类的cry方法}
}

综上所述,我们总结一下抽象类的使用场景和好处

1.用抽象类可以把父类中相同的代码,包括方法声明都抽取到父类,这样能更好的支持多态,一提高代码的灵活性。2.反过来用,我们不知道系统未来具体的业务实现时,我们可以先定义抽象类,将来让子类去实现,以方便系统的扩展。

3.3 模板方法设计模式

学习完抽象类的语法之后,接下来,我们学习一种利用抽象类实现的一种设计模式。先解释下一什么是设计模式?设计模式是解决某一类问题的最优方案

设计模式在一些源码中经常会出现,还有以后面试的时候偶尔也会被问到,所以在合适的机会,就会给大家介绍一下设计模式的知识。

那模板方法设计模式解决什么问题呢?模板方法模式主要解决方法中存在重复代码的问题

比如A类和B类都有sing()方法,sing()方法的开头和结尾都是一样的,只是中间一段内容不一样。此时A类和B类的sing()方法中就存在一些相同的代码。
在这里插入图片描述
怎么解决上面的重复代码问题呢? 我们可以写一个抽象类C类,在C类中写一个doSing()的抽象方法。再写一个sing()方法,代码如下:

// 模板方法设计模式
public abstract class C {// 模板方法public final void sing(){System.out.println("唱一首你喜欢的歌:");doSing();System.out.println("唱完了!");}public abstract void doSing();
}

然后,写一个A类继承C类,复写doSing()方法,代码如下

public class A extends C{@Overridepublic void doSing() {System.out.println("我是一只小小小小鸟,想要飞就能飞的高~~~");}
}

接着,再写一个B类继承C类,也复写doSing()方法,代码如下

public class B extends C{@Overridepublic void doSing() {System.out.println("我们一起学猫叫,喵喵喵喵喵喵喵~~");}
}

最后,再写一个测试类Test

public class Test {public static void main(String[] args) {// 目标:搞清楚模板方法设计模式能解决什么问题,以及怎么写。B b = new B();b.sing();}
}

综上所述:模板方法模式解决了多个子类中有相同代码的问题。具体实现步骤如下

1步:定义一个抽象类,把子类中相同的代码写成一个模板方法。
第2步:把模板方法中不能确定的代码写成抽象方法,并在模板方法中调用。
第3步:子类继承抽象类,只需要父类抽象方法就可以了。

总结

以上就是今天要讲的内容,本文介绍了多态、final、抽象类的介绍,不同场景下的使用和相关的注意事项。

http://www.dtcms.com/a/264413.html

相关文章:

  • 8.Docker镜像讲解
  • 大模型-分布式论文一瞥
  • twikitFKS: 基于 twikit 2.3.1 的改进版本
  • 【Python】numpy数组常用数据处理(测试代码+api例程)
  • BFD故障检测技术之概述
  • TypeScript 安装使用教程
  • QML通过XMLHttpRequest实现HTTP通信
  • 如何使用bedtools、convert2bed、gff2bed提取基因序列
  • C++ 快速回顾(六)
  • 设计模式精讲 Day 22:模板方法模式(Template Method Pattern)
  • Coze(扣子):基础学习
  • Python应用指南:利用高德地图API获取公交+地铁可达圈(二)
  • OpenCV图像梯度处理详解:原理、API与实战代码解析
  • 【Cyberstrikelab】lab3
  • AngularJS 安装使用教程
  • 转矩常数KT
  • 什么是数据孤岛?如何解决数据孤岛问题?
  • Wisdom SSH 与宝塔面板:深度对比剖析
  • 机器学习在智能教育中的应用:个性化学习路径与学习效果评估
  • socket编程
  • JavaEE线程概念
  • Git 运行.sh文件
  • js filter()
  • Linux 终止进程
  • 【ArcGIS】矢量数据的叠加分析
  • 面试拷打-20250701
  • LLM面试12
  • vite项目中引入tailwindcss,难倒AI的操作
  • day48
  • 目前最火的agent方向-A2A快速实战构建(二): AutoGen模型集成指南:从OpenAI到本地部署的全场景LLM解决方案