2011-07-28 33 views
9

從REPL恆定:添加顯式類型爲val防止VAL被用作註釋

scala> final val x = "x" 
x: java.lang.String("x") = x 

scala> @javax.persistence.Table(name = x) case class foo() 
defined class foo 

scala> final val x:java.lang.String = "x" 
x: java.lang.String = x 

scala> @javax.persistence.Table(name = x) case class foo() 
<console>:6: error: annotation argument needs to be a constant; found: x 
     @javax.persistence.Table(name = x) case class foo() 

有人可以解釋爲什麼沒有這種類型僅適用?

+0

爲什麼使用關鍵字'final'? – paradigmatic

+0

final是創建下面Daniel提到的字面常量所必需的。沒有它,你會得到上面提到的同樣的錯誤。 – scalapeno

回答

8

如果沒有這個類型,final val的行爲就像是一個常量 - 在編譯時標識符會被它的值替換。使用該類型時,它將成爲某處存儲的內容的參考,這些內容不能用於註釋。

這被限定在本說明書的4.1節:

恆定值的定義是形式

final val x = e 

其中e是一個常量表達式(§6.24)的。最終修飾符必須是 ,並且不能給出類型註釋。對常數值x的引用本身被視爲常量表達式;在 生成的代碼它們被定義的右邊 方e所取代。

這是您可以在Scala中獲得真正的命名常量的唯一方法。它們具有性能優勢,它們確實不會發生變異(即使是final val,類型也可以通過反射進行更改),當然,它們也可以用於註釋。

+0

我猜想那是發生了什麼,但爲什麼它會這樣工作?這樣做有什麼好處嗎?有沒有這種情況下這是一個有用的功能? – scalapeno

+0

@ tritium6我擴展了我的答案,但不是在註釋中使用足夠有用的情況嗎? –

+0

感謝您的擴展。你是對的,註解案例很有用。我的意思是,對於類型化表達式有沒有一個有用的例子 - 爲什麼你想要一個最終的val是一個引用的情況? – scalapeno