注解将元信息和定义关联起来。例如,注解方法前的@deprecated
会使得编译器在该方法被调用时打印一条警告。
1 | object DeprecationDemo extends App { |
上述代码可以通过编译但是编译器会打印一条警告:“there was one deprecation warning”。
注解子句用于其后的第一个定义或者声明。一个定义或者声明的前面可以出现不止一个注解子句,而它们的顺序并不重要。
确保编码正确的注解
某些注解会在条件不满足的情况下导致编译失败。例如,注解@tailrec
可以确保一个方法是尾递归。尾递归可以使得内存需求是固定的。下面是该注解在计算阶乘的方法中的使用情况:
1 | import scala.annotation.tailrec |
factorialHelper
方法拥有注解@tailrec
,可以确保该方法的确是尾递归的。如果我们按照下面的方式改变该方法的实现,则会编译失败:
1 | import scala.annotation.tailrec |
我们将得到提示信息“Recursive call not in tail position”。
影响代码生成的注解
有些注解(如@inline
)会影响代码的生成(即生成的jar文件跟不使用注解相比可能具有不同的字节大小)。内联(inlining)的意思是将方法体中的代码直接插入到调用的位置。这样生成的字节码会更长,但是运行会更快。使用注解@inline
无法确保一个方法会变成内联的,当且仅当通过了关于生成代码规模的一些尝试之后,编译器会将该方法变成内联的。
Java注解
在写与Java进行互操作的Scala代码时,在注解的语法上有些不同点需要注意。
注:在使用Java注解时必须带上选项-target:jvm-1.8
。
Java可以通过注解的形式来拥有用户自定义的元数据。注解的关键特性是依赖于对指定的名-值对进行初始化。例如我们需要一个注解来追踪某些类的来源,可能会这样来定义:
1 | @interface Source { |
接下来可以这样来使用:
1 | @Source(URL = "http://coders.com/", |
在Scala中使用注解像是在调用构造器,要实例化一个Java注解需要指定参数名:
1 | @Source(URL = "http://coders.com/", |
当注解仅有一个元素的时候这种语法便有点繁琐。所以习惯上,如果元素名称被指定为value
,那么在Java中可以用类似于构造器的语法:
1 | @interface SourceURL { |
然后这样使用:
1 | @SourceURL("http://coders.com/") |
这个例子中,Scala的用法也是类似的:
1 | @SourceURL("http://coders.com/") |
这里mail
元素被指定了一个默认值,所以不需要为它显式提供一个值。然而,如果需要给它提供值,在Java中不能混搭这两种形式:
1 | @SourceURL(value = "http://coders.com/", |
Scala则在这方面提供了更多的灵活性:
1 | @SourceURL("http://coders.com/", |