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 代码时,注解语法有一些需要注意的差异。注意:确保对 Java 注解使用 -target:jvm-1.8 选项。

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 ...

此页面的贡献者