Scala 導覽

註解

語言

註解將元資訊與定義關聯在一起。例如,方法前的註解 @deprecated 會導致編譯器在使用該方法時印出警告。

object DeprecationDemo extends App {
  @deprecated("deprecation message", "release # which deprecates method")
  def hello = "hola"

  hello
}
object DeprecationDemo extends App:
  @deprecated("deprecation message", "release # which deprecates method")
  def hello = "hola"

  hello

這會編譯,但編譯器會印出警告:「有一個不建議使用的警告」。

註解子句套用於其後的第一個定義或宣告。一個定義和宣告前面可以有多個註解子句。這些子句的順序並不重要。

確保編碼正確性的註解

如果未滿足某個條件,某些註解實際上會導致編譯失敗。例如,註解 @tailrec 確保方法是 尾遞迴。尾遞迴可以保持記憶體需求不變。以下是它在計算階乘的方法中的使用方式

import scala.annotation.tailrec

def factorial(x: Int): Int = {

  @tailrec
  def factorialHelper(x: Int, accumulator: Int): Int = {
    if (x == 1) accumulator else factorialHelper(x - 1, accumulator * x)
  }
  factorialHelper(x, 1)
}
import scala.annotation.tailrec

def factorial(x: Int): Int =

  @tailrec
  def factorialHelper(x: Int, accumulator: Int): Int =
    if x == 1 then accumulator else factorialHelper(x - 1, accumulator * x)
  factorialHelper(x, 1)

方法 factorialHelper 具有 @tailrec,可確保方法確實是尾遞迴。如果我們將 factorialHelper 的實作變更為以下內容,它將會失敗

import scala.annotation.tailrec

def factorial(x: Int): Int = {
  @tailrec
  def factorialHelper(x: Int): Int = {
    if (x == 1) 1 else x * factorialHelper(x - 1)
  }
  factorialHelper(x)
}
import scala.annotation.tailrec

def factorial(x: Int): Int =
  @tailrec
  def factorialHelper(x: Int): Int =
    if x == 1 then 1 else x * factorialHelper(x - 1)
  factorialHelper(x)

我們將會收到訊息「遞迴呼叫不在尾端位置」。

影響程式碼產生的註解

某些註解(例如 @inline)會影響產生的程式碼(也就是說,如果沒有使用註解,您的 jar 檔可能會有不同的位元組)。內嵌表示在呼叫位置插入方法主體中的程式碼。產生的位元組碼較長,但希望執行速度較快。使用註解 @inline 並無法確保方法將會內嵌,但如果且僅如果符合產生的程式碼大小的一些啟發法,它將會導致編譯器執行此動作。

某些註解(例如 @main)會影響產生的程式碼(也就是說,如果沒有使用註解,您的 jar 檔可能會有不同的位元組)。方法上的 @main 註解會產生可執行程式,並將方法呼叫為進入點。

Java 註解

撰寫與 Java 互通的 Scala 程式碼時,註解語法有一些差異需要注意。注意:請務必將 -target:jvm-1.8 選項與 Java 註解搭配使用。

Java 以 註解的形式提供使用者定義的元資料。註解的一項主要功能是,它們仰賴指定名稱值對來初始化其元素。例如,如果我們需要一個註解來追蹤某些類別的來源,我們可能會將其定義為

@interface Source {
  public String url();
  public String mail();
}

然後套用如下所示

@Source(url = "https://coders.com/",
        mail = "[email protected]")
public class MyJavaClass extends TheirClass ...

Scala 中的註解應用程式看起來像建構函式呼叫,要實例化 Java 註解,必須使用命名參數

@Source(url = "https://coders.com/",
        mail = "[email protected]")
class MyScalaClass ...

如果註解只包含一個元素(沒有預設值),這種語法相當繁瑣,因此,根據慣例,如果名稱指定為 value,則可以使用類似建構函式的語法在 Java 中套用

@interface SourceURL {
    public String value();
    public String mail() default "";
}

然後套用如下所示

@SourceURL("https://coders.com/")
public class MyJavaClass extends TheirClass ...

在這種情況下,Scala 提供了相同的可能性

@SourceURL("https://coders.com/")
class MyScalaClass ...

使用預設值指定 mail 元素,因此我們不需要明確提供它的值。但是,如果我們需要提供一個值,那麼在 Java 中我們也必須明確命名 value 參數

@SourceURL(value = "https://coders.com/",
           mail = "[email protected]")
public class MyJavaClass extends TheirClass ...

Scala 在這方面提供了更大的靈活性,因此我們可以選擇僅命名 mail 參數

@SourceURL("https://coders.com/",
           mail = "[email protected]")
class MyScalaClass ...

此頁面的貢獻者