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

Java final关键字与抽象类深度解析

二、final关键字

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

2.1 final修饰符的特点(面试题)

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

- final修饰类:该类称为最终类,特点是不能被继承 - final修饰方法:该方法称之为最终方法,特点是不能被重写。 - final修饰变量:该变量只能被赋值一次。
  • 接下来我们分别演示一下,先看final修饰类的特点

public class Test1 { // 目标: final的作用 ​ } ​ // final修饰类:该类称为最终类,特点是不能被继承 // 应用场景: 比如工具类, 只需要使用静态方法, 不需要被继承 final class A{} class B extends A{} // 此时就会报错
  • 再来演示一下final修饰方法的特点

public class Test1 { // 目标: final的作用 ​ } ​ // 2、final修饰方法:该方法称之为最终方法,特点是不能被重写。 class C{ public final void test(){ ​ } } class D extends C{ @Override public void test() { // 此时会报错 ​ } }
  • 再演示一下final修饰变量的特点

    • 情况一

    • 情况二

    • 情况三

2.2 补充知识:常量

刚刚我们学习了final修饰符的特点,在实际运用当中经常使用final来定义常量。先说一下什么是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); } }
  • 关于常量的原理,同学们也可以了解一下:在程序编译后,常量会“宏替换”,出现常量的地方,全都会被替换为其记住的字面量,这样可以保证使用常量和直接用字面量的性能是一样的。把代码反编译后,其实代码是下面的样子

public class FinalDemo2 { public static void main(String[] args) { // 编译时会直接将SCHOOL_NAME转成胜雅教育, 不存在根据名称找值的问题, 所以性能是一样的 System.out.println("胜雅教育"); System.out.println("胜雅教育"); System.out.println("胜雅教育"); System.out.println("胜雅教育"); System.out.println("胜雅教育"); System.out.println("胜雅教育"); System.out.println("胜雅教育"); } }

三、抽象类

同学们,接下来我们学习Java中一种特殊的类,叫抽象类。为了让同学们掌握抽象类,会先让同学们认识一下什么是抽象类以及抽象类的特点,再学习一个抽象类的常见应用场景。

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 { @Override public void test() { ​ } }
  • 子类继承父类如果不复写父类的抽象方法,要想不出错,这个子类也必须是抽象类

//B类基础A类,此时B类也是抽象类,这个时候就可以不重写A类的抽象方法 public abstract class B extends A { ​ }

3.2 抽象类的好处

接下来我们用一个案例来说一下抽象类的应用场景和好处。

好处: 多个类中只要有重复代码(包括相同的方法签名),我们都应该抽取到父类中去,此时,父类中就有可能存在只有方法签名的方法,这时,父类必定是一个抽象类了,我们抽出这样的抽象类,就是为了更好的支持多态。

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

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

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

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

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

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

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

public class Test2 { public static void main(String[] args) { // 目标:掌握抽象类的使用场景和好处. Animal a = new Dog(); a.cry(); //这时执行的是Dog类的cry方法 } }

再学一招,假设现在系统有需要加一个Pig类,也有叫的行为,这时候也很容易原有功能扩展。只需要让Pig类继承Animal,复写cry方法就行。

public class Pig extends Animal{ @Override public void cry() { System.out.println(getName() + "嚯嚯嚯~~~"); } }

此时,创建对象时,让Animal接收Pig,就可以执行Pig的cry方法

public class Test2 { public static void main(String[] args) { // 目标:掌握抽象类的使用场景和好处. Animal a = new Pig(); a.cry(); //这时执行的是Pig类的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{ @Override public void doSing() { System.out.println("我是一只小小小小鸟,想要飞就能飞的高~~~"); } }

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

public class B extends C{ @Override public 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.cnnetsun.cn/news/1768621.html

相关文章:

  • 从音频降噪到图像滤波:傅里叶、拉普拉斯、Z变换在实际工程中的选择指南
  • 告别重复搬砖!OpenClaw从零搭建可操作系统级AI智能体,自动化提效10倍实战指南
  • CLion 2025.1.1 + CubeMX + CMake:一站式配置STM32调试与烧录环境(以F103C8T6为例)
  • 使用 Deepseek 识别招聘陷阱(以卖保险为例)
  • 蕙兰瑜伽与素食,让程序员告别亚健康的生活方式
  • DeepFlow Agent 故障排查指南:注册失败、协议解析、资源识别与配置方式谛
  • 3分钟掌握网盘直链下载助手:免费高速下载六大网盘的终极方案
  • RK芯片定制化armbian系统:从根文件系统到GPU驱动优化
  • Seata部署后TC、TM、RM总报错?从日志和监控面板快速定位问题(附常见坑点)
  • 别再乱删了!手把手教你用官方工具彻底卸载Autodesk全家桶(3ds Max/CAD)
  • 上了一堆 BI 工具,为什么业务部门还是在用 Excel?
  • 超越wx.uploadFile!小程序多图上传终极方案:自定义FormData+后端接收详解
  • 冒泡排序详解
  • 告别WinForm重写噩梦!.NET8+Avalonia实现C#工业上位机Windows/统信UOS双平台兼容,成本直降90%
  • 内网K8s集群基石:保姆级教程搞定containerd、runc、CNI三件套离线安装
  • 2026届必备的六大降AI率网站解析与推荐
  • Python原生AOT编译方案2026深度适配手册(Windows/macOS/Linux三端全兼容避坑清单)
  • 亲测绍兴柯桥geo推广厂家排名
  • 从高斯到蒙特卡洛:在Sentaurus Sprocess中如何为你的离子注入选择最合适的模拟模型?
  • 网易云音乐体验升级:BetterNCM插件管理器全攻略
  • SOLIDWORKS右键菜单功能消失?3分钟快速恢复‘打包‘‘重命名‘功能(附注册表修复指南)
  • Artemis僵尸网络:从注册表篡改看Windows持久化攻击
  • 5大核心优势!Open Canvas对比OpenAI Canvas:开源AI协作工具如何重塑你的工作流
  • Verilog任务与函数实战:如何优化模块化设计
  • 飞书文档批量导出架构实战:企业级知识库迁移的高效解决方案
  • LAYONTHEGROUND伎
  • Hagicode.Libs:统一集成多个 AI 编程助手 CLI 的工程实践米
  • Docker 容器中运行 AI CLI 工具:用户隔离与持久化卷实战指南瀑
  • 别再手动P图了!用Python+Flask 5分钟搭建一个车牌图片生成API(支持蓝黄绿白黑牌)
  • 单调队列优化多重背包 学习笔记 详解弊