Day297.final&不可变性 -Juc

Posted 阿昌喜欢吃黄桃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day297.final&不可变性 -Juc相关的知识,希望对你有一定的参考价值。

final&不可变性

一、什么是不可变性(Immutable)

  • 如果对象在被创建后,状态就不能被修改,那么它就是不可变的
  • 这个对象不能被修改指:
    • 对象指向(引用)不可变
    • 字段不可变
    • 成员变量不可变
  • 案列person对象,age和name属性都不能再变

被final修饰的类属性

/******
 @author 阿昌
 @create 2021-06-13 16:08
 *******
 *      不可变的对象,演示其他类无法修改这个对象
 *      public也不行
 */
public class Person {
    final int age = 18;
    final String name = "achang";
}

测试修改被final修饰的类属性,发现编译都过不了

image-20210613161252073

如果这个类,有一个可修改的成员变量,他不被final修饰,那么这个类就不具备不可变性:↓↓↓

image-20210613161459507

  • 具有不可变性的对象,一定线程安全!!!我们不需要采取任何额外的安全措施,也可以保证线程安全

二、final的作用

1、早期

  • 锁定
  • 效率

早起Java实现版本中,会将final修饰的方法转为内嵌调用

内嵌调用

一个方法调用另外一个final方法,那么就吧这个final方法里面的东西全部都挪过来。

相当于在同一个方法里调用完成整个工作。不是方法之间调来调去,减少性能损耗


2、现在

  • 类防止被继承
  • 方法防止被重写
  • 变量防止被修改
  • 天生 线程安全 ,不需要额外的同步开销
  • 设计的清晰

三、final的3种用法

1、修饰变量

①含义

被final修饰的变量,意味着值不能被修改

如果变量是对象,那么对象的引用不能变,但是对象自身的内容依然可以变化

image-20210613162651340


②3种变量赋值时机

  • final instance variable(类中的final属性)

    • 赋值时机

    属性被声明为final后,改变量则只能被赋值一次。且一旦被赋值,final的变量就不能在改变,无论如何也不会变

    1、声明变量的等号右边直接赋值

    image-20210613164037186

    2、构造函数中赋值

    image-20210613164206089

    3、类的初始化代码块中赋值(不常用)

    image-20210613164429666

    如果不采用第一种赋值方法,那么就必须从第二、三种挑一种赋值,而不能不赋值,不然会报错;这个是final语法所规定的

image-20210613163756519


  • final static variable(类中的static final属性)

    • 赋值时机

    除了在声明变量的等号右边直接赋值外,static final变量还可以用static初始代码块赋值,但是不能用普通的初始代码块赋值

    1、声明变量的等号右边直接赋值

    image-20210613164833350

​ 2、static初始代码块赋值

image-20210613164852713


  • final local variable(方法中的final变量)

    • 赋值时机

    和前面两种不同,由于这里的变量是在方法里的;所以没有构造函数,也不存在初始代码块

    不规定赋值时机,只要求在使用前必须赋值,这个方法中的非final变量的要求也是一样的

image-20210613165325574


③为什么要规定赋值时机?

如果初始化不赋值,那后续的赋值,就是从null变成你的赋值

这就违反了final不变形的原则了


2、修饰方法

①构造方法不允许final修饰

image-20210613165941995

②不可被重写,也就是不能被override

即便是子类有同样名字的方法,那也不能override,这个和static方法是一个道理

image-20210613170327647


3、修饰类

  • 不可被继承
    • String就是被final修饰

image-20210613170849296


四、final的注意点

image-20210613171227617


五、不变性和final的关系

不变形并意味着,简单地用final修饰就是不可变

  • 对于基本数据类型,确实被final修饰后就具备不可变性

  • 但是对于对象类型,需要该对象保证自身被创建后,状态永远不会变才可以

  • 满足以下条件时↓↓↓,对象才满足不可变性

image-20210613174251098


六、栈封闭技术

image-20210613174821313

方法内的变量,多个线程之间不共享

他不会被其他线程所访问到

  • 代码演示
/******
 @author 阿昌
 @create 2021-06-13 17:49
 *******
 *      演示栈封闭的两种情况,基本变量 和 对象
 *      先演示线程争抢带来错误结果,然后把变量放到方法内,情况就变了
 */
public class StackConfinement implements Runnable {
    //类共享变量,被两个线程共享
    int index = 0;

    public void inThread(){
        //方法内局部变量,多个线程之间不共享
        int neverGoOut = 0;
        for (int i = 0; i < 10000; i++) {
            neverGoOut++;
        }
        System.out.println("栈内保护的数字是线程安全的: "+neverGoOut);
    }

    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            index++;
        }
        inThread();
    }

    public static void main(String[] args) throws InterruptedException {
        StackConfinement r = new StackConfinement();

        Thread thread1 = new Thread(r);
        Thread thread2 = new Thread(r);

        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();

        System.out.println(r.index);
    }
}

image-20210613175510983


以上是关于Day297.final&不可变性 -Juc的主要内容,如果未能解决你的问题,请参考以下文章

React中的不可变性

JavaScript中的不可变性(Immutability)

String的不可变性

字符串的不可变性--转载

04.字符串的不可变性

java中String的不可变性