Scala入门-注解(Annotations)

Scala入门-注解(Annotations)

注解(Annotations)

注解将元信息与定义联系起来。例如,如果一个带有注解@deprecated的方法被调用了,编译器就会打印一条警告。

object DeprecationDemo extends App {
  @deprecated
  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,可以确保其确实是尾部递归的。如果就将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)
}

我们将会得到消息“Recursive call not in tail position”。

影响代码生成的注解

一些像@inline这样的注解会影响代码生成(也就说生成的jar文件跟不用注解相比可能具有不同的字节)。内联的意思是将方法体内的代码插入到该方法被调用的位置。这样生成的结果字节码会变长,但是运行速度会变快。使用注解@inline无法确保方法一定会变成内联的,但是当且仅当关于代码规模的一些试探被满足时,编译器就会将其编译为内联的。

Java注解

当写与Java交互的Scala代码时,关于注解语法有一些不同点需要注意。注:在使用Java注解时需要带上选项-target:jvm-1.8

Java具有以注解的形式表示的用户自定义元数据。注解的一个关键特征是它们通过指定name-value对来初始化它们的元素。例如,如果我们需要一个注解来跟踪一些类的来源,可以这样定义

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

如果注解只包含一个元素(没有默认值),这个语法是相当冗长的,所以习惯上,如果name被指定为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 ...

参考资料

本文译自Tour Of Scala – Annotations

上一篇:Scala入门-By-name参数(By-name parameters)

下一篇:Scala入门-默认参数值(Default Parameter Values)

发表评论

电子邮件地址不会被公开。 必填项已用*标注