在Java中,final关键字用于声明不可变的实体,可以用于变量、方法和类。
介绍
一般变量与其值的内存空间之间就像是用绳索连接一样,可以被套到其他位置的内存空间。而final变量与其值的内存空间之间则是用镣铐连接,二者永远拴在一起,无法分离。
我们常常有一个误区,即用final修饰的变量其值是永远无法改变的。但如果理解了final的形象含义,就会发现我们犯了逻辑错误:final的定义只是说某一变量与某段内存空间的连接是无法改变的,但并没有提及内存空间的值是否可以改变。
那么,为了考察final变量引用的内存空间的值是否能够改变,我们分为两种情况:
- final修饰的可变变量
- final修饰的不可变变量
final修饰的可变变量
可变变量值的改变本身就是修改它指向的内存空间的值,是否被final修饰并不影响其值的修改,因此,final修饰的可变变量,其值是可以改变的。举例如下:(StringBuiler为mutable可变变量)
public static void main(String[] args){
final StringBuilder sb = new StringBuilder("ab");
System.out.println(sb);
sb.append("c");
System.out.println(sb);
}
final修饰的不可变变量
不可变变量值的改变对应的底层原因是变量指向了另一段内存空间,而final的修饰阻止了这种情况的存在,那我们能不能通过一定手段改变此变量指向的内存空间的值呢?答案是绝对否定的!不变对象一旦被创建,其指向的值不能被修改!因为指向的值是常量,无法被修改。(详情看下面科普)注意,这一特性是不可变变量本身的性质,与是否被final修饰无关。因此,final修饰的不可变变量,其值是不可以改变的。
科普
在Java中,常量通常存储在常量池中。常量池是Java虚拟机中的一块特殊内存区域,用于存储编译时期确定的各种字面量常量,比如字符串常量、基本类型常量等。这些常量在编译阶段就已经确定,并且它们在整个程序运行期间保持不变。常量池的设计旨在节省内存空间,提高运行效率。