Java经典面试题——谈谈 final、finally、finalize 有什么不同?
典型回答
final 可以用来修饰类、方法、变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展, final 的变量是不可以修改的,而 final 的方法也是不可以重写的(override)。
finally 则是 Java 保证重点代码一定要被执行的一种机制。我们可以使用 try - finally 或者 try - catch - finally 来进行类似关闭 JDBC 连接、保证 unlock 锁等动作。
finalize 是基础类 java.lang.Object 的一个方法,它的设计目的是保证对象被垃圾收集前完成特定资源的回收。finalize 机制现在已经不推荐使用,并且在 JDK9 开始被标记为 deprecated。
知识扩展
关于 final
final 是一个非访问修饰符,仅适用于变量,方法或类。
final 修饰变量
当使用 final 关键字声明类成员变量或局部变量后,其值不能被再次修改;也经常和 static 关键字一起,作为 类常量 使用。
很多时候会容易把 static 和 final 关键字混淆,static 作用于成员变量用来表示只保存一份副本,而 final 的作用是用来保证变量不可变。
如果 final 变量是引用,这意味着该变量不能重新绑定到引用另一个对象,但是可以更改该引用变量指向的对象的内部状态,即可以从 final 数组或 final 集合中添加或删除元素。最好用全部大写来表示 final 变量,使用下划线来分隔单词。
//一个final成员常量
final int THRESHOLD = 5;
//一个空的final成员常量
final int THRESHOLD;
//一个静态final类常量
static final double PI = 3.141592653589793;
//一个空的静态final类常量
static final double PI;
初始化final变量:
我们必须初始化一个final变量,否则编译器将抛出编译时错误。final 变量只能通过初始化器或赋值语句初始化一次。初始化 final 变量有三种方法:
- 可以在声明它时初始化 final 变量。这种方法是最常见的。如果在声明时未初始化,则该变量称为空 final 变量。下面是初始化空 final 变量的两种方法。
- 可以在 instance-initializer 块 或内部构造函数中初始化空的final变量。如果您的类中有多个构造函数,则必须在所有构造函数中初始化它,否则将抛出编译时错误。
- 可以在静态块内初始化空的 final 静态变量。
这里注意有一个很普遍的误区。很多人会认为 static 修饰的 final常量必须在声明时就进行初始化,否则会报错。但其实则不然,我们可以先使用 static final 关键字声明一个类常量,然后再在静态块内初始化空的 final 静态变量。
何时使用 final 变量 ?
普通变量和 final 变量之间的唯一区别是我们可以将值重新赋值给普通变量;但是对于 final 变量,一旦赋值,我们就不能改变 final 变量的值。因此,final 变量必须仅用于我们希望在整个程序执行期间保持不变的值。
final 修饰类
当使用 final 关键字声明一个类时,它被称为 final 类。被声明为 final 的类不能被扩展(继承)。final 类有两种用途:
- 一个是彻底防止被继承,因为 final 类不能被扩展。例如,所有包装类如 Integer,Float 等都是 final 类。我们无法扩展它们。
- final 类的另一个用途是创建一个类似于 String 类的不可变类。只有将一个类定义成为 final 类,才能使其不可变。
Java支持把 class 定义成 final,似乎违背了面向对象编程的基本原则,但在另一方面,封闭的类也保证了该类的所有方法都是固定不变的,不会有子类的覆盖方法需要去动态加载。这给编译器做优化时提供了更多的可能,最好的例子是 String,它就是 final类,Java 编译器就可以把字符串常量(那些包含在双引号中的内容)直接变成 String 对象,同时对运算符 “+” 的操作直接优化成新的常量,因为 final 修饰保证了不会有子类对拼接操作返回不同的值。
final关键字在效率上的作用主要可以总结为以下三点:
- 缓存:final 配合 static 关键字提高了代码性能,JVM和Java应用都会缓存 final 变量。
- 同步:final 变量或对象是只读的,可以安全的在多线程环境下进行共享,而不需要额外的同步开销。
- 内联:使用 final 关键字,JVM会显式地主动对方法、变量及类进行内联优化。
关于 finally
try 关键字最后可以定义 finally 代码块。 finally 块中定义的代码,总是在 try 和任何 catch 块之后、方法完成之前运行。
正常情况下,不管是否抛出或捕获异常 finally 块都会执行。
啥时候 finally 不会被执行 ?
尽管通常编写 finally 代码块是为了这段代码一定被执行到,但是也有一些特殊情况会导致 JVM 不会执行 finally 代码块。
如果操作系统中断了我们的程序,那么 finally 代码块可能就不能被执行。也有很多其他类似的行为导致 finally 代码块不被执行。
调用 System.exit 函数
try {System.out.println("Inside try");System.exit(1);
} finally {System.out.println("Inside finally");
}
结果
Inside try
调用 halt 函数
try {System.out.println("Inside try");Runtime.getRuntime().halt(1);
} finally {System.out.println("Inside finally");
}
结果
Inside try
守护线程
如果守护线程刚开始执行到 finally 代码块,此时没有任何其他非守护线程,那么虚拟机将退出,此时 JVM 不会等待守护线程的 finally 代码块执行完成。
Runnable runnable = () -> {try {System.out.println("Inside try");} finally {try {Thread.sleep(1000);System.out.println("Inside finally");} catch (InterruptedException e) {e.printStackTrace();}}
};
Thread regular = new Thread(runnable);
Thread daemon = new Thread(runnable);
daemon.setDaemon(true);
regular.start();
Thread.sleep(300);
daemon.start();
输出
Inside tryInside tryInside finally
try 代码块中无限循环
try {System.out.println("Inside try");while (true) {}
} finally {System.out.println("Inside finally");
}
try 代码块出现无限循环,且不出现异常,finally 也将永远得不到执行。
常见陷阱
忽视异常
finally 代码块包含返回语句,没有处理未捕获的异常。
try {System.out.println("Inside try");throw new RuntimeException();
} finally {System.out.println("Inside finally");return "from finally";
}
此时,try 代码块中的 RuntimeException 会被忽略,函数返回 "from finally"字符串。
覆盖其他返回语句
如果 finally 代码块中存在返回语句,则 try 和 catch 代码块如果存在返回语句就会被忽略。
try {System.out.println("Inside try");return "from try";
} finally {System.out.println("Inside finally");return "from finally";
}
此段代码总是返回 “from finally” 。
改变 throw 或 return 行为
如果再 finally 代码块中扔出异常,则 try 和 catch 中的异常扔出或者返回语句都将被忽略。
try {System.out.println("Inside try");return "from try";
} finally {throw new RuntimeException();
}
这段代码永远都不会有返回值,总是会抛出 RuntimeException。
相关文章:
Java经典面试题——谈谈 final、finally、finalize 有什么不同?
典型回答 final 可以用来修饰类、方法、变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展, final 的变量是不可以修改的,而 final 的方法也是不可以重写的(override)。 finally 则是 Java 保…...
C#的Version类型值与SQL Server中二进制binary类型转换
使用C#语言编写的应用程序可以通过.NET Framework框架提供的Version类来控制每次发布的版本号,以便更好控制每次版本更新迭代。 版本号由两到四个组件组成:主要、次要、内部版本和修订。 版本号的格式如下所示, 可选组件显示在方括号 ([ 和…...
软测入门(五)接口测试Postman
Postman 一款Http接口收工测试工具。如果做自动化测试会使用jemter做。 安装 去官网下载即可。 https://www.postman.com/downloads/?utm_sourcepostman-home 功能介绍 页面上的单词基本上都能了解,不多介绍。 转代码&注释 可将接口的访问转为其他语言的…...
UWB通道选择、信号阻挡和反射对UWB定位范围和定位精度的影响
(一)介绍检查NLOS操作时需要考虑三个方面:(1)由于整体信号衰减,通信范围减小。(2)由于直接路径信号的衰减,导致直接路径检测范围的减小。(3)由于阻…...
linux基本功之列之wget命令实战
文章目录前言一. wget命令介绍二. 语法格式及常用选项三. 参考案例3.1 下载单个文件3.2 使用wget -o 下载文件并改名3.3 -c 参数,下载断开链接时,可以恢复下载3.4 wget后台下载3.5 使用wget下载整个网站四. 补充与汇总常见用法总结前言 大家好ÿ…...
学习ROS时针对gazebo相关的问题(重装与卸载是永远的神)
ResourceNotFound:gazebo_ros 错误解决 参考:https://blog.csdn.net/weixin_42591529/article/details/123869969 当将机器人加载到gazebo时,运行launch文件出现如下错误 这是由于缺少gazebo包所导致的。 解决办法:...
几个C语言容易忽略的问题
1 取模符号自增问题 我们不妨尝试写这样的程序 #include<stdio.h> int main(){int n,t5;printf("%d\n",7%(-3));//1printf("%d\n",(-7)%3);//-1while(--t)printf("%d\n",t);t5;while(t--)printf("%d\n",t);return 0; } 运行…...
CentOS 7.9安装Zabbix 4.4《保姆级教程》
CentOS 7.9安装Zabbix 4.4一、配置一览二、环境准备设置Selinux和firewalld设置软件源1.配置ustc CentOS-Base源2.安装zabbix 4.4官方源3.安装并更换epel源4.清除并生成缓存三、安装并配置Zabbix Server安装zabbix组件安装php安装mariadb并创建数据库修改zabbix_server.conf设置…...
路由器与交换机的区别(基础知识)
文章目录交换机路由器路由器和交换机的区别(1)工作层次不同(2)数据转发所依据的对象不同(3)传统的交换机只能分割冲突域,不能分割广播域;而路由器可以分割广播域(4&#…...
Python基础学习9——函数
基本概念 函数是一种能够完成某项任务的封装工具。在数学中,函数是自变量到因变量的一种映射,通过某种方式能够使自变量的值变成因变量的值。其实本质上也是实现了某种值的转换的任务。 函数的定义 在python中,函数是利用def来进行定义&am…...
项目中的MD5、盐值加密
首先介绍一下MD5,而项目中用的是MD5和盐值来确保密码的安全性; 1. md5简介 md5的全称是md5信息摘要算法(英文:MD5 Message-Digest Algorithm ),一种被广泛使用的密码散列函数,可以产生一个128位…...
电商项目后端框架SpringBoot、MybatisPlus
后端框架基础 1.代码自动生成工具 mybatis-plus (1)首先需要添加依赖文件 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.2</version></dependency><de…...
2023年03月IDE流行度最新排名
点击查看最新IDE流行度最新排名(每月更新) 2023年03月IDE流行度最新排名 顶级IDE排名是通过分析在谷歌上搜索IDE下载页面的频率而创建的 一个IDE被搜索的次数越多,这个IDE就被认为越受欢迎。原始数据来自谷歌Trends 如果您相信集体智慧&am…...
华为校招机试 - 数组取最小值(Java JS Python)
目录 题目描述 输入描述 输出描述 用例 题目解析 JavaScript算法源码 Java算法源码...
20 客户端服务订阅的事件机制剖析
Nacos客户端服务订阅的事件机制剖析 我们已经分析了Nacos客户端订阅的核心流程:Nacos客户端通过一个定时任务,每6秒从注册中心获取实例列表,当发现实例发生变化时,发布变更事件,订阅者进行业务处理,然后更…...
ThreadPoolExecutor中的addWorker方法
在看线程池源码的时候看到了这么一段代码 private boolean addWorker(Runnable firstTask, boolean core) {retry:for (int c ctl.get();;) {// Check if queue empty only if necessary.if (xxx)return false;for (;;) {if (xxx)return false;if (xxx)break retry;if (xxx)c…...
9 有线网络的封装
概述 IPC设备一般都带有网口,支持以有线网络方式接入NVR和其他平台。有线网络的使用比较简单,主要操作有:设置IP地址、子网掩码、网关、DHCP等。在封装有线网络前,我们需要先封装DHCP客户端管理类,用于管理各种网络的DHCP功能。 DHCP客户端管理类 DHCP客户端管理类的头文件…...
Linux----网络基础(2)--应用层的序列化与反序列化--守护进程--0226
文章中有使用封装好的头文件,可以在下面连接处查询。 Linux相关博文中使用的头文件_Gosolo!的博客-CSDN博客 1. 应用层 我们程序员写的一个个解决我们实际问题, 满足我们日常需求的网络程序, 都是在应用层 1.2 协议 我们在之前的套接字编程中使用的是…...
uipath实现滑动验证码登录
现实需求 在进行RPA流程设计过程中,遇到登录系统需要滑动验证的情况,如图所示: 此时需要在RPA流程设计中,借助现有的活动完成模拟人工操作,完成验证登录操作。 设计思路 这个功能流程的设计思路大体如下: …...
openai-chatGPT的API调用异常处理
因为目前openai对地区限制的原因,即使设置了全局代理使用API调用时,还是会出现科学上网代理的错误问题。openai库 0.26.5【错误提示】:raise error.APIConnectionError(openai.error.APIConnectionError: Error communicating with OpenAI: …...
幻境·流金惊艳效果:微观世界视角——细胞结构、晶体生长、电路板纹路超清生成
幻境流金惊艳效果:微观世界视角——细胞结构、晶体生长、电路板纹路超清生成 “流光瞬息,影画幻成。” 想象一下,你正透过一台超级显微镜,观察一个我们肉眼无法触及的微观世界。在那里,细胞壁的纹理如同精密的蜂巢&…...
OpenClaw新手避坑指南:nanobot部署5大常见配置错误
OpenClaw新手避坑指南:nanobot部署5大常见配置错误 1. 为什么需要这份避坑指南 上周我在本地部署OpenClaw的nanobot时,经历了整整两天的痛苦调试。明明按照文档一步步操作,却总是卡在奇怪的错误上。最崩溃的是,有些问题在官方文…...
设备重生:面向企业IT的激活锁解决方案
设备重生:面向企业IT的激活锁解决方案 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 问题诊断:激活锁困局与商业价值损失 企业设备管理的隐形成本 某教育机构IT主管王工近期…...
AI“龙虾热”背后:机遇与挑战并存
2026年,代号OpenClaw的AI智能体“龙虾”迅速引爆全球。它不仅能对话问答,还能独立完成多项任务。众多厂商跟进推出对标产品,产业链全面扩张,但背后也存在诸多问题。热潮背后的三重驱动“龙虾热”表层是春节AI红包大战流量普及与大…...
双系统安装完整指南——以双Win11为例
一、安装前的准备工作 1. 硬件与系统要求 CPU:支持 Windows 11(Intel 8 代 / AMD Ryzen 2000 及以上)主板: 支持 UEFI支持 TPM 2.0 磁盘: GPT 分区格式至少 120GB 空闲空间(建议每个系统 ≥ 80GB…...
递归对抗驱动的活系统:九层架构设计理念与理论体系构建【世毫九实验室原创理论】
递归对抗驱动的活系统:九层架构设计理念与理论体系构建方见华世毫九实验室摘要本文提出完整的活系统理论框架,以“系统持续生存与自主演化”为核心第一性原理,突破传统复杂系统、人工智能与偏微分方程理论中“追求稳定、消除矛盾、收敛最优”…...
面向生产的Chatgpt5.4:系统集成、架构模式与成本优化深度拆解
对于计划将顶级AI能力深度集成至自身产品与工作流的团队而言,理解Gemini 3.1 Pro的系统级特性、集成模式与全生命周期成本至关重要。国内开发者可通过RskAi(www.rsk.cn)等聚合平台,以零成本、国内直访的方式完成前期技术验证与原型…...
颠覆式数据主权革命:WeChatMsg如何让你的聊天记录真正归属自己
颠覆式数据主权革命:WeChatMsg如何让你的聊天记录真正归属自己 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/…...
绕过RK3588的RGA坑:手把手教你修改YOLOv8分割模型部署代码,用CPU预处理替代硬件加速
RK3588部署YOLOv8分割模型的稳定化实践:从RGA报错到CPU预处理方案优化 当你在RK3588开发板上部署YOLOv8分割模型时,是否遇到过这样的场景:模型转换和交叉编译一切顺利,却在运行时突然弹出"Failed to call RockChipRga interf…...
解锁AI创作自由:ComfyUI节点式工作流从入门到精通
解锁AI创作自由:ComfyUI节点式工作流从入门到精通 【免费下载链接】ComfyUI 最强大且模块化的具有图形/节点界面的稳定扩散GUI。 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI 你是否遇到过这样的困境:想要调整AI生成图像的某个细节…...
