java之final关键字详解

news/2025/2/10 23:49:00/

final关键字表示最终的、不可改变的

可以修饰以下维度:

1、修饰类

目的:不能被其他类继承

  • 该类为最终类,不能被其他类继承

  • 该类中的所有方法都是最终方法(隐式的被final修饰)

如图:即使手动添加final修饰方法,IDEA也会提醒该final可以移除

在开发中,哪些类需要定义为final呢?

  • final修饰类的初衷是不能让其他类继承该类,实际开发中,我们一般遵循"低耦合,高内聚合"的原则

  • 如果一个类被其他类继承,那么当父类被修改时,可能会造成子类报错,从而子类也需要同步修改,该条继承链为"高耦合"

综上,对于经常需要修改的类(迭代更新会经常改动的类),可以使用final修饰

2、修饰方法

目的:子类不能重写(覆盖)该方法

如图所示:子类重写父类中的最终方法,会出现错误

哪些方法需要定义为最终方法?

对继承没有太大意义的方法,或者父类自身特有的方法,这些方法不需要给子类使用,从而定义为最终方法,在类继承时,可以降低耦合度

3、修饰局部变量

作用:final修饰的变量是不可改变的

优点:不需要重复的创建对象

这里的不可改变又分为2种:

  • 对于基本数据类型,指的是数值不可改变

  • 对于引用数据类型,指的是变量对应的地址不可改变

这里区别来源于java内存分配方式:

  1. 在java中,基本数据类型定义的值是存储在栈中的

  1. 引用数据类型定义的名称是存储在栈中的,而对应的实例(值),是存储在堆中

3.1、基本数据类型

如图:内存中的值不可改变

3.2、引用数据类型

注意:这里不能使用String来举例,String是一个特殊的存储机制

以User类为例

@Data
@AllArgsConstructor
public class User{String name;Integer age;
}

fina修饰User对象,地址更改的示例代码:

public static void main(String[] args) {//1、声明User最终的局部变量,并name=张三/age=18存储在堆中final User user = new User("张三", 18);System.out.println("堆中的值name发生改变前,user对象存储的结果为:" + user);//2、修改最终变量user中,地址指向的堆中的值name=李四user.setName("李四");System.out.println("堆中的值name发生改变后,user对象存储的结果为:" + user);
}

示意图如下:user对象内存地址是不可改变的,而实际的值可以一致修改,耗用内存比重复创建对象小

4、修饰全局变量(属性)

作用与上述局部变量一致

注意以下4点

4.1、final修饰全局变量,必须手动赋初始值

全局变量在没有final修饰的情况下,默认是存在初始值的,如下:

public class FinalStudy {/** 为了能在主方法中直接获取到全局变量,这里使用static修饰 *///定义一个基本数据类型的全局变量astatic int a;//定义一个包装数据类型的全局变量bstatic Integer b;//定义一个引用类型的全局变量cstatic String c;public static void main(String[] args) {System.out.println("int的默认值为:" + a);System.out.println("Integer的默认值为:" + b);System.out.println("String的默认值为:" + c);}
}

结果为:

其实:引用数据类型的默认值都为null,而每一种基本数据类型都有其对应的默认值。

改造下上面的代码,当我们使用final修饰时,会报错,提示需要给初始值:

4.2、对于final修饰的全局变量,要么直接赋值,要么通过构造方法赋值

还是以上面的代码为例:

注意:由于构造方法为:与类同名,无返回类型且不允许static修饰的方法,从而需要去除上述的static修饰符

示例图如下:

4.3、对于未直接赋值的final类型的全局变量,所有的构造方法都必须对该变量进行赋值

案列1:

即:

我们也可以给无参构造放方法添加参数


http://www.ppmy.cn/news/35238.html

相关文章

第1节 线性回归模型

1. 模型概述 对于收集到的数据(xi,yi)(x_i,y_i)(xi​,yi​),建立线性回归模型yiθTxiεi(1)y_i\theta^{^T} x_i \varepsilon_i (1)yi​θTxi​εi​(1) 需要估计的参数为θT\theta^{^T}θT,我们的目的是让估计的参数θT\theta^{^T}θT和xix_ixi​…

OpenMV快速上手 | OpenMV硬件版本概述及HelloWorld

文章目录一、OpenMV1. 什么是OpenMV2. OpenMV版本2.1. OpenMV1(M4 V1)2.2. OpemMV2(M4 V2)2.3. OpenMV3(M7)2.4. OpenMV4(H7)二、OpenMV开发环境搭建三、hello world1. 连接OpenMV2.…

多线程代码案例-阻塞队列

hi,大家好,今天为大家带来多线程案例--阻塞队列 这块知识点也很重要,要好好掌握呀~~~ 🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸&#x…

【机器学习面试总结】————特征工程

【机器学习面试总结】————特征工程一、特征归一化为什么需要对数值类型的特征做归一化?二、类别型特征在对数据进行预处理时,应该怎样处理类别型特征?三、高维组合特征的处理什么是组合特征?如何处理高维组合特征?四、组合特征怎样有效地找到组合特征?五、文本表示模型…

数据迁移工具

1.Kettle Kettle是一款国外开源的ETL工具,纯Java编写,绿色无需安装,数据抽取高效稳定 (数据迁移工具)。 Kettle 中有两种脚本文件,transformation 和 job,transformation 完成针对数据的基础转换,job 则完成整个工作流的控制。 Kettle 中文名称叫水壶,该项目的主程序…

蓝桥杯嵌入式第六课--串口收发

前言串口作为一个考试中考察频率较高的考点,其套路比较固定,因此值得我们仔细把握。本节课主要着眼于快速配置实现 串口收发与串口的中断。CubeMX配置选择串口2配置异步收发模式基本参数设置(波特率、校验位等等)开启串口收发中断…

1、DRF实战总结:DRF特点、序列化与RESTful API规范

Django这种基于MVC开发模式的传统框架,非常适合开发基于PC的传统网站,因为它同时包括了后端的开发(逻辑层、数据库层) 和前端的开发(如模板语言、样式)。现代网络应用Web APP或大型网站一般是一个后台,然后对应各种客户端(iOS, android, 浏览…

香橙派5使用NPU加速yolov5的实时视频推理(二)

三、将best.onnx转为RKNN格式 这一步就需要我们进入到Ubuntu20.04系统中了,我的Ubuntu系统中已经下载好了anaconda,使用anaconda的好处就是可以方便的安装一些库,而且还可以利用conda来配置虚拟环境,做到环境与环境之间相互独立。…