答案的另一個問題是誤導。術語final
有兩個含義:a)對於Scala字段/方法和Java方法,它表示「不能在子類中重寫」,以及b)對於Java字段和JVM字節碼,這意味着「字段必須在構造函數中初始化並且不能被重新分配「。
標記爲val
(或者等價地,沒有修飾符的案例類參數)的類參數在第二意義上確實是最終的,因此線程安全。
這裏的證明:
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);
}
感謝您的澄清。你能看到我對這個問題的更新嗎?我還看到,對於沒有修飾符的非case類,聲明爲final的構造函數變量(如javap中所示)。 –
@retronym,我來到你的答案試圖找到我的問題的答案,[在Scala中的不變性和線程安全性](http://stackoverflow.com/questions/32113124/immutability-and-thread-safety-in-斯卡拉)。如您所知,Java中的'final'關鍵字也用於避免ctor指令的重定位,如[this]中所述(https://www.cs.umd.edu/~pugh/java/memoryModel /jsr-133-faq.html#finalRight)鏈接。所以,如果我已經理解了你的答案,那麼在Scala類中使用'val'字段就等於在Java類中聲明'final'字段,讓JMM正常工作? –