最近准备先清理一下告警,整理一下代码再继续开发。
然后遇到一个告警synchronization on a non-final field。
对这个告警的一些说明:
深入思考系列——"Synchronization on a non-final field"_枫夜求索阁的博客-优快云博客
大致意思是,如果不加final,那么这个synchronization里面的变量的引用就可能发生改变,导致synchronized失效,然后其他线程就会进入原本没有结束的synchronized代码块。
按我之前的理解,加了final就类似于C语言里面定义一个常量,定义以后就不能再修改了。然后我这个synchronized里面的变量,是会发生变化的,所以觉得应该不能直接加final。但是试了试加上去编译并没有报错。
就去查了查java的相关语法,发现java的这个final玩法很多,和我想的差别比较大。
上面的文章里面有final用法的详解。
我这边只涉及到使用final修饰变量,就只看变量相关的。
摘录一段文章中的内容:
final 修饰基本类型变量和引用类型变量的区别
当使用 final 修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。 但对于引用类型变量而言,它保存的仅仅是一个引用,final 只保证这个引用类型变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以发生改变。
这里的基本类型变量就是int,string这些。
引用类型变量指arraylist这些。
简单来说就是,对于arraylist这类变量,可以调用增删改查,赋值各种操作,但是不能new,例如final arraylist xxx; xxx = new arraylist,这种就会有问题。应该是这种操作会修改这个变量的引用。
再加一点关于变量加final能不能修改的讨论。
这里面有人讨论了同样的问题,简单总结一下,加了final,不能修改这个变量的地址,或者说变量的引用。所以对于基本数据类型和String这些,重新赋值就是修改了变量的地址,但是对于arraylist,map这些变量,使用set接口赋值,只是修改了其中的内容,arraylist还是旧的那个,没啥变化。