注解

注解将元信息和定义关联起来。例如,注解方法前的 @deprecated 会使得编译器在该方法被调用时打印一条警告。

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

  hello  
}

上述代码可以通过编译但是编译器会打印一条警告:“there was one deprecation warning”。

注解子句用于其后的第一个定义或者声明。一个定义或者声明的前面可以出现不止一个注解子句,而它们的顺序并不重要。

确保编码正确的注解

某些注解会在条件不满足的情况下导致编译失败。例如,注解 @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)
}

factorialHelper 方法拥有注解 @tailrec ,可以确保该方法的确是尾递归的。如果我们按照下面的方式改变该方法的实现,则会编译失败:

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)
}

我们将得到提示信息“Recursive call not in tail position”。

影响代码生成的注解

有些注解(如 @inline )会影响代码的生成(即生成的jar文件跟不使用注解相比可能具有不同的字节大小)。内联(inlining)的意思是将方法体中的代码直接插入到调用的位置。这样生成的字节码会更长,但是运行会更快。使用注解 @inline 无法确保一个方法会变成内联的,当且仅当通过了关于生成代码规模的一些尝试之后,编译器会将该方法变成内联的。

Java 注解

在写与 Java 进行互操作的 Scala 代码时,在注解的语法上有些不同点需要注意。

注:在使用 Java 注解时必须带上选项 -target:jvm-1.8

Java 可以通过注解的形式来拥有用户自定义的元数据。注解的关键特性是依赖于对指定的名-值对进行初始化。例如我们需要一个注解来追踪某些类的来源,可能会这样来定义:

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

接下来可以这样来使用:

@Source(URL = "http://coders.com/",
        mail = "support@coders.com")
public class MyClass extends HisClass ...

在 Scala 中使用注解像是在调用构造器,要实例化一个 Java 注解需要指定参数名:

@Source(URL = "http://coders.com/",
        mail = "support@coders.com")
class MyScalaClass ...

当注解仅有一个元素的时候这种语法便有点繁琐。所以习惯上,如果元素名称被指定为 value ,那么在 Java 中可以用类似于构造器的语法:

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

然后这样使用:

@SourceURL("http://coders.com/")
public class MyClass extends HisClass ...

这个例子中,Scala 的用法也是类似的:

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

这里 mail 元素被指定了一个默认值,所以不需要为它显式提供一个值。然而,如果需要给它提供值,在 Java 中不能混搭这两种形式:

@SourceURL(value = "http://coders.com/",
           mail = "support@coders.com")
public class MyClass extends HisClass ...

Scala 则在这方面提供了更多的灵活性:

@SourceURL("http://coders.com/",
           mail = "support@coders.com")
    class MyScalaClass ...
知识共享许可协议 BY 小鹏            此页面修订于 2019-07-17 14:11:54

results matching ""

    No results matching ""