并发学习--final

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
因为别人只能进行读取,却不能进行更改。
在这里插入图片描述
类用final反正被继承,方法用final防止被重写,变量用final防止被修改。
在这里插入图片描述
在这里插入图片描述
例子如下:
在这里插入图片描述
在这里插入图片描述
final修饰变量
在这里插入图片描述
在这里插入图片描述
代码演示如下:

package immutable;

public class FinalVariableDemo {
    // 如果不赋值直接报错
    private final int a = 6;
    private final int b;
    private final int c;
    
    // 赋值方式二,在构造函数中赋值
    public FinalVariableDemo(int b) {
        this.b = b;
    }
    
    // 赋值方式三,在代码块中赋值
    {
        c = 6;
    }
}

在这里插入图片描述

package immutable;

public class FinalVariableDemo {
    // 如果不赋值直接报错
    private static final int a = 6;
    private static final int b;
    // 赋值方式二,静态代码块
    static {
        b = 6;
    }
    // 它无法在构造函数中赋值
}

在这里插入图片描述

package immutable;

public class FinalVariableDemo {
    
    void testFinal(){
        final int b;
    }
}

在这里插入图片描述
普通的对象,可能初始化以后为null,但是,final不行,初始化就得给他赋值,在方法中,使用之前就得给他显式赋值。因为它是不可变的。
final修饰方法
在这里插入图片描述
在这里插入图片描述
final修饰类
在这里插入图片描述
final的注意点
在这里插入图片描述
如果一个变量知道它不会变那么就用final修饰,这样也起到了提示的作用。
不变性和final的关系
在这里插入图片描述
如何利用final实现对象不可变呢?
在这里插入图片描述
首先,把所有属性都声明为final不一定可以实现不可变了,如果属性是对象类型的话,只是对象的引用不可变。
然后,一个属性是对象类型的对象,也可能是不可变对象,只要该对象只提供读取的方法,不提供更改的方法即可。
例子如下:

package immutable;

import java.util.HashSet;
import java.util.Set;

public class ImmutableDemo {
    // private修饰,所以,外界无法进行获取,也无法进行更改了。
    private final Set<String> students = new HashSet<>(4);
    // 对students的添加只在构造函数中做过一次,在别的地方没有进行添加。
    public ImmutableDemo(){
        students.add("小卢");
        students.add("小孙");
        students.add("小李");
    }
    
    // 为外界提供读取方法
    public boolean isStudent(String name){
        return students.contains(name);
    }
}

由此可见,看对象可不可变,主要还是看外界能不能对他里面内容进行更改。
在这里插入图片描述
在这里插入图片描述

package immutable;

import java.util.concurrent.*;

/**
 *  描述: 栈封闭技术
 *  演示栈封闭的两种情况,基本变量和对象
 *  先演示线程争抢带来的错误结果,然后把变量放到方法内,情况就变了
 */
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) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 2, 0, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
        StackConfinement stackConfinement = new StackConfinement();
        for (int i = 0; i < 2; i++) {
            threadPoolExecutor.submit(stackConfinement);
        }
        threadPoolExecutor.shutdown();
        while(!threadPoolExecutor.isTerminated()){
        }
        System.out.println("index:" + stackConfinement.index);

    }
}

结果如下:
在这里插入图片描述
结论分析:实例变量会有线程安全的问题,但是,方法内的变量只能是当前线程可以访问它,所以,不会存在线程安全问题,它具有栈封闭的功能。
在这里插入图片描述
答案是true和false
加了final 以后,就是常量了,所以,c会自己等于wukong2,由于a已经建立过,所以,c会知道a的地址
而d没有fianl,编译器不能提前知道d的值,所以e要在运行时确定,所以,是在堆上生成wukong2。所以,他们指向的不是一个地方。

package immutable;

public class FinalStringDemo2 {
    public static void main(String[] args) {
        String a = "wukong2";
        // 通过方法获得,编译器也无法在编译时获得,所以,也是生成在堆上
        final String b = getDashxiong();
        String c = b + 2;
        System.out.println(a == c);
    }

    private static String getDashxiong() {
        return "wukong";
    }
}

这个返回是false

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值