Java关键字之final

简介: Java final 关键字

1 前言

final 的意思是不变的,一般来说可以用于以下三种场景:

  1. 被 final 修饰的类,表明该类是无法继承的;
  2. 被 final 修饰的方法,表明该方法是无法覆写的;
  3. 被 final 修饰的变量,说明该变量在声明的时候,就必须初始化完成,而且以后也不能修改其内存地址。

注意:对于 List、Map 这些集合类来说,被 final 修饰后,是可以修改其内部值的,但却无法修改其初始化时的内存地址。

2 修饰的对象

final 可以用来修饰变量、字段、方法和类。

2.1 变量

可以将变量声明为 final 。final 变量的值一旦分配了就无法再修改了。在一次赋值之前,final 变量必须是明确未赋值的,否则会产生编译错误。如果 final 变量包含对对象的引用,则对象的状态可能会通过对对象的操作进行更改,但变量将始终引用相同的对象。这同样适用于数组,因为数组也是对象;如果一个 final 变量持有一个数组的对象,则可以通过对数组的操作修改数组中的元素,但是该变量始终会引用相同的数组。

注意,如果 final 用于局部变量,那么它可以不用初始化,而如果用于类中的某个字段,那么它必须进行初始化,否则会产生编译错误。

空 final 是指其声明缺少初始化器的 final 变量。

常数变量是一个用常量表达式初始化的基本类型或String类型的 final 变量。 变量是否为常数变量与类的初始化,二进制兼容性和明确赋值有关。

有三种变量会被隐式声明为 final :接口中的字段,try-with-resources 语句中的局部变量以及multi-catch子句中的异常参数。 一个单一的 catch 子句中的 exception 参数永远不会隐式声明为 final ,但是它可以被认为效果等同于 final 。

某些未被声明为 final 变量实际上可以认为效果等同于 final 变量:

  • 声明带有初始化器且满足下列所有条件的局部变量:
  • 永远不会作为赋值操作符的左操作数出现
  • 永远不会作为前缀或后缀递增或递减操作符的操作数出现
  • 声明缺少初始化器且满足下列所有条件的局部变量:
  • 无论何时它作为赋值操作符的左操作数出现,都是明确未赋过值的,并且在本次赋值操作前未被明确赋值。即它是明确未赋过值的,并且在本次赋值操作的右操作数之后未被明确赋值
  • 永远不会作为前缀或后缀递增或递减操作符的操作数出现
  • 方法、构造器、lambda 和异常参数在明确其是否可以认定为等同于 final 时可以被认为是声明带有初始化器的局部变量

如果变量在效果上等同于 final ,那么对其声明添加 final 修饰符并不会引入任何编译错误。相反地,在合法程序中被声明为 final 的局部变量和参数,如果将它们的 final 修饰符移除,那么它们在效果上会等同于 final 。

2.2 类

类可以被声明为 final ,如果一个 final 类的名字出现在另一个类声明的 extends 子句中,会产生编译错误,这意味着 final 类不能有任何子类。

如果一个类同时被声明为 final 和 abstract ,也会产生编译错误,因为这样的类是永远无法实现的。

因为一个 final 类不能有任何子类,所以 final 类的方法永远都不会被覆写。

如果将一个没有被声明的 final 类声明为 final ,那么当这个类的已有子类的二进制文件被加载时,就会抛出一个 VerifyError ,因为 final 类不能有任何子类。因此不推荐在广泛分布的类中进行这种变更。

反之,将一个声明为 final 的类不再声明为 final ,不会破坏与已有二进制文件的兼容性。

2.3 方法

方法可以被声明为 final 以阻止子类覆写或者隐藏它。

如果试图覆写或者隐藏 final 方法,会产生编译错误。

private 方法和所有在 final 类中声明的方法表现就如 final方法一样,因为它们是不可能被覆写的。

在运行时,机器码生成器或优化器可以“内联” final 方法的方法体,将方法的调用替换为其方法体中的代码。内联处理必须保留方法调用的语义。特别是,如果实例方法调用的目标为null,那么即使该方法是内联的,也必须抛出空指针异常。一个Java编译器必须确保异常在正确的位置上被抛出,这样在方法调用之前,传递给方法的实际参数将被按正确的顺序计算过。

2.4 字段

字段可以被声明为 final 。类和实例变量(static 和 非 static 字段)都可以被声明为 final。

空 final 类变量必须在声明它的类的静态初始化器中赋过值,否则会产生编译错误。

空 final 实例变量必须在声明它的类的每一个构造器的末尾赋过值,否则会产生编译错误。

参考资料

目录
相关文章
|
12月前
|
存储 缓存 安全
除了变量,final还能修饰哪些Java元素
在Java中,final关键字不仅可以修饰变量,还可以用于修饰类、方法和参数。修饰类时,该类不能被继承;修饰方法时,方法不能被重写;修饰参数时,参数在方法体内不能被修改。
160 3
|
9月前
|
缓存 安全 Java
Volatile关键字与Java原子性的迷宫之旅
通过合理使用 `volatile`和原子操作,可以在提升程序性能的同时,确保程序的正确性和线程安全性。希望本文能帮助您更好地理解和应用这些并发编程中的关键概念。
228 21
|
8月前
|
Java C语言
课时8:Java程序基本概念(标识符与关键字)
课时8介绍Java程序中的标识符与关键字。标识符由字母、数字、下划线和美元符号组成,不能以数字开头且不能使用Java保留字。建议使用有意义的命名,如student_name、age。关键字是特殊标记,如蓝色字体所示。未使用的关键字有goto、const;特殊单词null、true、false不算关键字。JDK1.4后新增assert,JDK1.5后新增enum。
146 4
|
7月前
|
存储 安全 Java
深入理解 Java 中的 instanceof 关键字
本文深入解析了 Java 中的 `instanceof` 关键字,探讨其在类型判断中的作用。作为二元操作符,`instanceof` 可用于检查对象是否为某类实例或实现特定接口,避免类型转换异常 (`ClassCastException`)。文章通过多态性下的类型判断、安全类型转换、接口实现检测及集合元素类型判定等实际应用场景,展示了 `instanceof` 的强大功能。掌握该关键字可提高代码健壮性,确保运行时类型安全。
499 0
|
11月前
|
存储 缓存 Java
Java 并发编程——volatile 关键字解析
本文介绍了Java线程中的`volatile`关键字及其与`synchronized`锁的区别。`volatile`保证了变量的可见性和一定的有序性,但不能保证原子性。它通过内存屏障实现,避免指令重排序,确保线程间数据一致。相比`synchronized`,`volatile`性能更优,适用于简单状态标记和某些特定场景,如单例模式中的双重检查锁定。文中还解释了Java内存模型的基本概念,包括主内存、工作内存及并发编程中的原子性、可见性和有序性。
294 5
Java 并发编程——volatile 关键字解析
|
10月前
|
Java 编译器 开发者
Java中的this关键字详解:深入理解与应用
本文深入解析了Java中`this`关键字的多种用法
1606 9
|
10月前
|
JSON Java 数据挖掘
利用 Java 代码获取淘宝关键字 API 接口
在数字化商业时代,精准把握市场动态与消费者需求是企业成功的关键。淘宝作为中国最大的电商平台之一,其海量数据中蕴含丰富的商业洞察。本文介绍如何通过Java代码高效、合规地获取淘宝关键字API接口数据,帮助商家优化产品布局、制定营销策略。主要内容包括: 1. **淘宝关键字API的价值**:洞察用户需求、优化产品标题与详情、制定营销策略。 2. **获取API接口的步骤**:注册账号、申请权限、搭建Java开发环境、编写调用代码、解析响应数据。 3. **注意事项**:遵守法律法规与平台规则,处理API调用限制。 通过这些步骤,商家可以在激烈的市场竞争中脱颖而出。
|
11月前
|
缓存 安全 Java
Java volatile关键字:你真的懂了吗?
`volatile` 是 Java 中的轻量级同步机制,主要用于保证多线程环境下共享变量的可见性和防止指令重排。它确保一个线程对 `volatile` 变量的修改能立即被其他线程看到,但不能保证原子性。典型应用场景包括状态标记、双重检查锁定和安全发布对象等。`volatile` 适用于布尔型、字节型等简单类型及引用类型,不适用于 `long` 和 `double` 类型。与 `synchronized` 不同,`volatile` 不提供互斥性,因此在需要互斥的场景下不能替代 `synchronized`。
3396 3
|
12月前
|
JavaScript 前端开发 Java
java中的this关键字
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。自学前端2年半,正向全栈进发。若我的文章对你有帮助,欢迎关注,持续更新中!🎉🎉🎉
188 9
|
12月前
|
设计模式 JavaScript 前端开发
java中的static关键字
欢迎来到瑞雨溪的博客,博主是一名热爱JavaScript和Vue的大一学生,致力于全栈开发。如果你从我的文章中受益,欢迎关注我,将持续分享更多优质内容。你的支持是我前进的动力!🎉🎉🎉
244 8