Scala final vs val并发可见性
发布时间:2020-12-16 09:43:19 所属栏目:安全 来源:网络整理
导读:在Java中,当跨多个线程(通常)使用对象时,最好将字段设为final。例如, public class ShareMe { private final MyObject obj; public ShareMe(MyObject obj) { this.obj = obj; }} 在这种情况下,obj的可视性在多个线程之间是一致的(假设obj也有所有final字
在Java中,当跨多个线程(通常)使用对象时,最好将字段设为final。例如,
public class ShareMe { private final MyObject obj; public ShareMe(MyObject obj) { this.obj = obj; } } 在这种情况下,obj的可视性在多个线程之间是一致的(假设obj也有所有final字段),因为它是使用final关键字安全构造的。 在scala中,它不会显示val编译到最后的引用,而是val是scala中的语义阻止您重新分配变量(Scala final variables in constructor)。如果scala构造函数变量没有被定义为final,那么它们会遇到同样的问题(在actor中使用这些对象时)? 解决方法
另一个问题的答案是误导的。术语final有两个含义:a)对于Scala字段/方法和Java方法,它意味着“不能在子类中被覆盖”,以及b)对于Java字段,并且在JVM字节码中,这意味着“该字段必须在构造函数中初始化并不能重新分配“。
标记为val的类参数(或等效地,没有修饰符的case类参数)在第二种意义上确实是最终的,因此线程安全。 以下是证明: scala> class A(val a: Any); class B(final val b: Any); class C(var c: Any) defined class A defined class B defined class C scala> import java.lang.reflect._ import java.lang.reflect._ scala> def isFinal(cls: Class[_],fieldName: String) = { | val f = cls.getDeclaredFields.find(_.getName == fieldName).get | val mods = f.getModifiers | Modifier.isFinal(mods) | } isFinal: (cls: Class[_],fieldName: String)Boolean scala> isFinal(classOf[A],"a") res32: Boolean = true scala> isFinal(classOf[B],"b") res33: Boolean = true scala> isFinal(classOf[C],"c") res34: Boolean = false 或者使用javap,可以方便地从REPL运行: scala> class A(val a: Any) defined class A scala> :javap -private A Compiled from "<console>" public class A extends java.lang.Object implements scala.ScalaObject{ private final java.lang.Object a; public java.lang.Object a(); public A(java.lang.Object); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |