Scala基礎之註解(annotation

在學習Scala的過程當中,總會碰到一些註解:java

// Predef.scala @inline def implicitly[T](implicit e: T) = e @deprecated("Use `sys.error(message)` instead", "2.9.0") def error(message: String): Nothing = sys.error(message) // Spark RDD.scala abstract class RDD[T: ClassTag]( @transient private var sc: SparkContext, ....) 

通常來講,註解能夠做用於vals, vars, defs, classes, objects, traits 和 types甚至是表達式的後面。編程

import scala.reflect.runtime.{ universe => ju } def meth[A: ju.TypeTag](xs: List[A]) = xs match { case strList: List[String @ unchecked] if ju.typeTag[A].tpe =:= ju.typeOf[String] => "list of Strings" case barList: List[Bar @ unchecked] if ju.typeTag[A].tpe =:= ju.typeOf[Bar] => "list of Bar" } 

咱們知道List[T]在運行時會被類型擦除,至關於變成List。@unchecked 告訴compiler不要去檢查這個,不然就會報下面的warning。併發

non-variable type argument String in type pattern List[String] is unchecked since it is eliminated by erasure 

另外, 註解實際上也是普通的類只不過編譯器對其進行特殊的支持,因此咱們才能那樣書寫。好比說,咱們常見的序列號的註解。app

class SerialVersionUID(uid: Long) extends scala.annotation.StaticAnnotation @SerialVersionUID(13567156) class B {} @deprecated("use newShinyMethod() instead", "since 2.3") def bigMistake() = //... bigMistake scalac -deprecation Deprecation2.scala warning: method bigMistake in class B is deprecated: use newShinyMethod() instead println(bigMistake) ^ one warning found 

@volatile

實際上這個註解或是關鍵字,大多用於被併發訪問的共享變量。在JVM內存模型中happens-before規則有一條就是volatile變量法則(有興趣能夠閱讀Java併發編程實踐 第16章Java內存模型),對於volatile變量,同一變量的寫操做老是先於讀操做。學習

class Person(@volatile var name: String) { def set(changedName: String) { name = changedName } } 

@tailrec

這個註解是與尾遞歸優化有關的。優化

// 階乘 def factorial(n: Int) = { @tailrec def go(n: Int, acc: Int): Int = { if (n <=0) acc else go(n-1, acc * n) // 尾遞歸,顧名思義方法的調用也必須出如今返回值的位置 } go(n, 1) } 

@Unchecked

通常是在模式匹配的時候用到的,告訴編譯器有些地方不用"檢查"了。如前所述,List[String @ unchecked]。ui

@transient

這個註解通常用於序列化的時候,標識某個字段不用被序列化。spa

import java.io.{ FileOutputStream, FileInputStream } import java.io.{ ObjectOutputStream, ObjectInputStream } class Hippie(val name: String, @transient val age: Int) extends Serializable object Serialization { val fos = new FileOutputStream("hippie.txt") val oos = new ObjectOutputStream(fos) val p1 = new Hippie("zml", 34) oos.writeObject(p1) oos.close() } object Deserialization extends App { val fis = new FileInputStream("hippie.txt") val ois = new ObjectInputStream(fis) val hippy = ois.readObject.asInstanceOf[Hippie] println(hippy.name) println(hippy.age) ois.close() } 運行以後的結果 zml 0 

因爲age被標記爲@transient,在反序列化的時候,就獲取不到原始值了因此被賦值爲默認值。scala

@inline

這個註解,在Scala.Predef中見到過一次。官方文檔中的解釋跟沒說同樣, 卻是StackOverflow上一個的答案,我的以爲比較能說明做用。code

Instead of a function call resulting in parameters being placed on the stack and an invoke operation occurring, the definition of the function is copied at compile time to where the invocation was made, saving the invocation overhead at runtime.

大體的意思就是@inline可以避免方法的參數被放到棧上,以及"顯示的調用"。由於編譯器在編譯的時候會將整個方法複製到它被調用的地方。

http://stackoverflow.com/questions/4593710/when-should-i-and-should-i-not-use-scalas-inline-annotation

相關文章
相關標籤/搜索