final关键字限制了什么?
形如final a = b
变量a不能修改其引用的指向,即a不能再指向新的引用地址,除此之外,final变量和非final变量在使用上没有任何区别
b的值是允许改变的
如果改变b的值的时候不将b指向新的引用地址,则等同于修改a的值
如果改变b的值的时候b指向了新的引用地址,则a的值并没有被改变,a仍然指向原始引用地址
不仅b的值可以改变,a的值也是允许改变的,只是不允许改变a的引用地址而已
一句话,final限制了引用地址的更改,而非地址中值的更改
final对象和不可变对象
final变量的本质是不能指向新的引用地址,而不是不能改变地址中的值,换句话说,final对象的值是可变的
如果一个final变量指向一个对象,而该对象的所有引用类型全局变量也都是final的,并且一直递推到最后一层依赖也都是final的,只有在此严格条件下,才可以说,final对象的值是完全不可修改的
值完全不可修改的对象为不可变对象
不可变对象一定是线程安全的
final对象则不然
类和方法上的final关键字
非本文重点
一个final类不允许被继承,但,完全不意味着该类的实例为final对象
一个final方法不允许被重写
package test;
import java.util.HashMap;
import java.util.Map;
/**
* @author liuwei
* @date 2019-09-10 09:29
* @desc 引用类型变量上的final关键字
*/
public class FinalTest {
private String variableString = "origin string";
private final String finalString = variableString;
private Map<String,String> variableMap = new HashMap<>();
private final Map<String,String> finalMap = variableMap;
/**
* 前言
* 0.无论是实例还是静态引用类型变量,均适用以下解释
* 1.引用类型变量赋值实际只是为其指定了一个引用地址,该引用地址存放了对象的实际数据
* 2.引用类型变量对其全局变量的修改操作实际是对其引用地址中数据的修改
* 3.引用类型变量再次赋值实际是为其指定另一个引用地址
*/
public static void main(String[] args) {
FinalTest test = new FinalTest();
//1.下文代码编译报错:Cannot assign a value to final variable 'finalString'/'finalMap'
//test.finalString="new string";
//test.finalMap = new HashMap<>();
//2.以下代码运行结果:[variableString] new string [finalString] origin string
//String类型是特殊的Java类型,关键在于JDK不提供改变String对象引用地址中值的方法,因此对String对象只能进行引用地址改变
//String的特殊还在于对字面常量的共享,同一个作用域中只维持一份字面常量值
//此时的variableString已经指向了新的引用地址,但finalString仍然会指向原始引用地址
test.variableString = "new string";
test.printString();
//3.以下代码运行结果:[variableMap] {keyFin=value, keyVar=value} [finalMap] {keyFin=value, keyVar=value}
test.variableMap.put("keyVar","value");
test.finalMap.put("keyFin","value");
test.printMap();
}
public void printString(){
System.out.println("[variableString] "+variableString+" [finalString] "+finalString);
}
public void printMap(){
System.out.println("[variableMap] "+variableMap+" [finalMap] "+finalMap);
}
}