1、什么是不可变性?

如果对象在被创建后,状态就不能修改,那么就是不可变的

据有不可变性的对象一定是线程安全的,我们不需要对其采取任何额外的安全措施,也能够保证线程安全。
**

2、final的作用

类防止被继承,方法防止被重写,变量防止被修改

天生线程安全

2.1、final 修饰变量

final修饰变量意味着值不能更改,final修饰对象, 意味着对象引用不能变,但是对象内容可以变化

  • 类属性中的成员变量

赋值时机:
(1)声明变量等号右边直接赋值
(2)构造方法中赋值
(3)类的初始代码块赋值

  • 类属性中的静态变量

(1)声明变量等号右边直接赋值
(2)静态代码块赋值

  • 方法中的变量

(1)不规定赋值时机,但是使用前必须赋值

  1. public class FinalVariable {
  2. private final int a = 5;
  3. private final static int b = 5;
  4. // private final static int b = 5; 静态变量第一种赋值时机
  5. // static {
  6. // b = 5; 静态变量第二种赋值时机
  7. // }
  8. // private final int a = 5; 实例变量第一种赋值时机
  9. // public FinalVariable(int a) {
  10. // this.a = a; 实例变量第二种赋值时机
  11. // }
  12. // {
  13. // a = 5; 实例变量第三种赋值时机
  14. // }
  15. public void doSomething(){
  16. //方法中的变量 不规定赋值时机,但是使用前必须赋值
  17. final int a = 5;
  18. }
  19. }

2.2、final修饰方法

不允许修饰构造方法

修饰普通方法,表示不可被重写,和static类似

静态方法不可被重写(但是子类和父类可以有相同名字的方法)

2.3、final修饰类

不可被继承

String

3、不变性和final的关系

不变性并不意味着简单被final修饰后就是不可变的

  • 对于基本类型,确实被final修饰后据有不变性
  • 但是对于对象类型,需要对象保证自身被创建后,状态永远不会变才可以

如何利用final做到对象不可变

  • 对象创建后,状态不可修改
  • 所有属性都是final修饰的
  • 对象创建过程中没有发生溢出

栈封闭技术,方法内的变量线程不共享,线程安全

4、 面试题

  1. public static void main(String[] args) {
  2. //指向常量池
  3. String a = "java2";
  4. // final 修饰编译时已经确定,被当作编译时期的常量使用
  5. final String b = "java";
  6. //指向常量池的java
  7. String c = "java";
  8. //编译时发现b是常量,就直接得到d的值为java2,刚好声明了java2,所以a和d指向常量池的java2
  9. String d = b + 2;
  10. // c不是final修饰,d的值要到运行时才确定
  11. String e = c + 2;
  12. System.out.println(a == d);
  13. System.out.println(a == e);
  14. }