传名参数
传名参数仅在使用时求值。在类型之前添加=>,即可令参数为传名参数。
定义传名参数
def ggg(kkk: => Int) = kkk * 999
传名参数的优势在于,如果函数体中没有使用过此参数,此参数不会求值,并且它们也只会被求一次值。
如果参数是计算密集的求值或者长运行时间的代码(例如,获取URL),传名参数提供的延迟参数计算直到参数被使用的机制有助于提升性能。
注解
注解与定义的元数据相关联。例如,方法之前的@deprecated注解用于告知编译器在方法被使用时打印一条警告信息。
使用注解
@deprecated("dasdfjasldkjfa;sdfasdf", "155131353")
def hello = "hola"
注解用于紧跟在其后的首个定义或声明。可以有一个以上的注解位于定义或声明之前,这些注解的顺序并不会产生什么影响。
1 确保编码的注解
在没能满足指定条件时,一些注解可以令编译失败。例如,@tailrec可以确保访问为尾递归。尾递归可以令内存需求保持不变。
# 使用@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)
}
2 影响代码生成的注解
一些注解(例如,@inline)将会影响生成的代码。(即,如果使用了此注解,生成的jar文件将会有些许不同)。内联即将方法体中的代码插入调用点。作为结果的字节码将会更长,但是运行起来可能更快。使用@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元素已经被提供了默认值,所以不需要显式为其提供值。但是,如果需要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 ...