1、什么是不可变性?
如果对象在被创建后,状态就不能修改,那么就是不可变的
据有不可变性的对象一定是线程安全的,我们不需要对其采取任何额外的安全措施,也能够保证线程安全。
**
2、final的作用
类防止被继承,方法防止被重写,变量防止被修改
天生线程安全
2.1、final 修饰变量
final修饰变量意味着值不能更改,final修饰对象, 意味着对象引用不能变,但是对象内容可以变化
- 类属性中的成员变量
 
赋值时机:
(1)声明变量等号右边直接赋值
(2)构造方法中赋值
(3)类的初始代码块赋值
- 类属性中的静态变量
 
(1)声明变量等号右边直接赋值
(2)静态代码块赋值
- 方法中的变量
 
(1)不规定赋值时机,但是使用前必须赋值
public class FinalVariable {private final int a = 5;private final static int b = 5;// private final static int b = 5; 静态变量第一种赋值时机// static {// b = 5; 静态变量第二种赋值时机// }// private final int a = 5; 实例变量第一种赋值时机// public FinalVariable(int a) {// this.a = a; 实例变量第二种赋值时机// }// {// a = 5; 实例变量第三种赋值时机// }public void doSomething(){//方法中的变量 不规定赋值时机,但是使用前必须赋值final int a = 5;}}
2.2、final修饰方法
不允许修饰构造方法
修饰普通方法,表示不可被重写,和static类似
静态方法不可被重写(但是子类和父类可以有相同名字的方法)
2.3、final修饰类
不可被继承
String
3、不变性和final的关系
不变性并不意味着简单被final修饰后就是不可变的
- 对于基本类型,确实被final修饰后据有不变性
 - 但是对于对象类型,需要对象保证自身被创建后,状态永远不会变才可以
 
如何利用final做到对象不可变
- 对象创建后,状态不可修改
 - 所有属性都是final修饰的
 - 对象创建过程中没有发生溢出
 
栈封闭技术,方法内的变量线程不共享,线程安全
4、 面试题
public static void main(String[] args) {//指向常量池String a = "java2";// final 修饰编译时已经确定,被当作编译时期的常量使用final String b = "java";//指向常量池的javaString c = "java";//编译时发现b是常量,就直接得到d的值为java2,刚好声明了java2,所以a和d指向常量池的java2String d = b + 2;// c不是final修饰,d的值要到运行时才确定String e = c + 2;System.out.println(a == d);System.out.println(a == e);}
