一.本章要点

  • 可以为类、方法、字段、局部变量、参数、表达式、类型参数以及各种类型定义添加注解
  • 对于表达式和类型,注解跟在被注解的条目之后
  • 注解的形式有@Annotation、@Annotation(value)或@Annotation(name1=value1,...)
  • @volatile、@transient、@strictfp、@native分别生成等效的Java修饰符
  • 用@tailrec注解让你校验某个递归函数使用了尾递归化
  • assert函数利用了@elidable注解,可以从Scala程序中移除所有断言
  • 用@desprecated注解来标记已过时的特性 

二.什么是注解

  注解是插入到代码中以便有工具可以对它们处理的标签。工具可以在代码级别运作,也可以处理被编译器加入注解信息的类文件。可以对Scala使用Java注解或Scala注解。

  注:Java注解并不影响编译器如何将源码翻译成字节码(它们仅仅是往字节码中添加数据,以便外部工具可以利用它们),在Scala中,注解可以影响编译过程(如@BeanProperty会出发getter和setter方法生成)。

三.什么可以被注解

  类,方法,字段,局部变量,参数添加注解。

  注:可以同时添加多个注解,先后顺序没影响;

    主构造器添加注解时,注解应该放在构造器之前并加圆括号(注解无参数);

    表达式加注解,需要在表达式后加冒号,然后注解;

    参数类型,实际类型注解。。。  

四.注解参数

  Java注解可以有带名参数;参数名为value可以直接略去;大多数注解参数都有缺省值(如Junit的@Test默认timeout参数有默认为0)。

  Java注解的参数类型只能是:

      • 数值型的字面量;
      • 字符串;
      • 类字面量;
      • Java枚举;
      • 其他注解;
      • 上述类型的数组(但不能是数组的数组)

  Scala的注解的参数类型可以是任何类型。。。

五.注解实现

  注解必须扩展Annotation特质,例:

class unchecked extends annotation.Annotation

  注解类可以选择扩展StaticAnnotation或ClassfileAnnotation特质。StaticAnnotation在编译单元中可见(放置在Scala特有的元数据到类文件中)。而ClassfileAnnotation的本意是在类文件中生成Java注解元数据(Scala2.9不支持该特性)。

六.正对Java特性的注解

  Scala提供了一组与Java互操作的注解。

  1.Java修饰符

    对于那些不是很常用的Java特性,Scala使用注解,而不是修饰符关键字。

    如:

      @volatile注解将字段标记为易失的(可以被多个线程同时跟新),对应volatile;

      @transient将字段标记为瞬态的(不会被序列化,对临时保存的缓存数据或者能够从新计算的数据合理),在JVM转换为transient;

      @strictfp使用IEEE使用double值来进行浮点运算(计算更慢,代码移植性高),对应strictfp;

      @native标记C或C++方法,对应native

  2.标记接口

    Scala用注解@cloneable和@remote而不是Cloneable和java.rmi.Remote标记接口来标记被克隆和远程的对象。

    注:@seriliable已经过时,扩展scala.Serializable特质;

      对于可序列化的类,用@SerialVersionUID指定序列化版本

  3.受检异常

    和Scala不同,Java编译器会跟踪受检异常。如果从Java代码中调用Scala的方法,其签名应包含那些可能被抛出的受检异常(用@throws注解生成正确的签名)。

  4.变长参数

    @varargs注解可以从Java调用Scala的带有变长参数的方法。例:

def process(arg:String *)   =>
//scala编译器会把变长参数翻译称序列(在Java中费劲)
def process(args:Seq[String]) //加入@varargs会翻译称如下
process(String... args)

  5.JavaBeans

    @BeanProperty注解生成JavaBean风格的getter和setter方法;

    @BooleanProperty生成带有is前缀的getter方法,用于Boolean

七.用于优化的注解

  Scala类库中的有些注解可以控制编译器优化。

  1.尾递归

    递归调用有时能转换为循环,以节省栈空间。尾递归优化(由于计算过程的最后一步是递归调用同一个方法,因此它可以被变换为跳回到方法顶部的循环)。

    例:

object Util{
def sum(xs:Seq[Int]):BigInt={
if(xs.isEmpty) 0 else xs.head+sum(xs.tail)
}
}
//栈溢出错误
sum(1 to 1000000) //优化(Scala会自动应用尾递归优化)
def sum2(xs:Seq[Int],partial:BigInt):BigInt={
if (xs.isEmpty) partial else sum2(xs.tail,xs.head+partial)
}

    注:尽管Scala会尝试使用尾递归优化,但有时某些不太明显的原因会造成它无法这么做。如果有赖于编译器消除递归,可以加上@tailrec注解(如果不能呢个优化,则会报错)。

      对于消除递归,一个更加通用的机制叫”蹦床“,会执行一个循环,不停地调用函数,每个函数都返回下一个将被调用的函数,尾递归是每个函数都返回自己。

  2.跳跃表生成与内联

    在Java/C++中,switch语句通常可以被翻译成跳跃表(比if/else更高效)。

    Scala也会尝试对匹配语句生成跳跃表,可以用@switch注解检查Scala语句是不是被编译成了跳跃表,例:

(n:@switch) match{
case 0=>"Zero"
...
}

    内联:将方法调用替换为被调用的方法体,可以使用@inline和@noinline告诉编译器需不需要内联。

  3.可省略方法

    使用@elidable注解给可以在生产代码中移除的方法打上标记,elidable对象有如下数量值:使用scalac -Xelide-below INFO xx.scala编译(低于1000的方法会被忽略)

  4.基本类型的特殊化

    打包和解包基本类型的值是不高效的——在泛型代码中很常见。例:

def allDifferent[T](x:T,y:T,z:T)=x!=y&&x!=z&&y!=z
//调用之前每个值会包装成一个java.lang.Integer
allDifferent(1,2,3)
//也可以重载限定类型

    可以使用@specialized注解限定可选类型子集,例:

//自动生成各种类型的方法
def allDifferent[@specialized T](x:T,y:T,z:T)....
//限定子集
def allDifferent[@specialized(Long,Double) T]().....

八.用于错误和警告的注解

  如果给某个特性加上@deprecated注解,每当编译器遇到对这个特性使用时都会生成一个警告信息(有两个参数message和since);

  @deprecatedName可以被应用到参数上(单引号开头,检查名称是否过时,这是符号,效率比字符串高);

  @implicitNotFound注解用于某个隐式参数不存在时生成有意义的错误提示;

  @unchecked注解用于匹配不完整信息时取消警告信息;

  @uncheckedvariance注解会取消与型变相关的错误提示。。。  

九.练习

Scala学习十五——注解的更多相关文章

  1. Java编程思想学习(十五) 注解

    注解Annotation又叫元数据,是JDK5中引入的一种以通用格式为程序提供配置信息的方式.使用注解Annotation可以使元数据写在程序源码中,使得代码看起来简洁,同时编译器也提供了对注解Ann ...

  2. Scala学习十九——解析

    一.本章要点 文法定义中的二选一.拼接.选项和重复在Scala组合子解析器中对应|.~.opt和rep 对于RegexParsers而言,字符串字面量和正则表达式匹配的是词法单元 用^^来处理解析结果 ...

  3. Scala学习十八——高级类型

    一.本章要点 单例类型可用于方法串接和带对象参数的方法 类型投影对所有外部类的对象都包含了其他内部类的实例 类型别名给类型指定一个短小的名称 结构类型等效于”鸭子类型“ 存在类型为泛型的通配参数提供了 ...

  4. Scala学习十四——模式匹配和样例类

    一.本章要点 match表达式是更好的switch,不会有意外调入下一个分支 如果没有模式能够匹配,会抛出MatchError,可以用case _模式避免 模式可以包含一个随意定义的条件,称做守卫 你 ...

  5. Scala学习十——特质

    一.本章要点 类可以实现任意数量的特质 特质可以要求实现它们的类具备特定的字段,方法或超类 和Java接口不同,Scala特质可以提供方法和字段实现 当你将多个特质叠加在一起时,顺序很重要——其方法先 ...

  6. 强化学习(十五) A3C

    在强化学习(十四) Actor-Critic中,我们讨论了Actor-Critic的算法流程,但是由于普通的Actor-Critic算法难以收敛,需要一些其他的优化.而Asynchronous Adv ...

  7. Scala学习十六——XML处理

    一.本章要点 XML字面量<like>this</like>的类型为NodeSeq 可以在XML字面量中内嵌Scala代码 Node的child属性产出后代节点 Node的at ...

  8. Scala学习十二——高阶函数

    一.本章要点 在Scala中函数是”头等公民“(可以作为参数,返回值,赋值给其他); 可以创建匿名函数,通常还会交给其他函数; 函数参数可以给出需要稍后执行的行为; 许多集合方法都接受函数参数,将函数 ...

  9. 智能车学习(十五)——K60野火2013版例程

    一.中断函数注册方法: 1.格式: 配置某个功能的中断 注册中断函数 开启中断 2.一个例子 pit_init_ms(PIT0,);//定时中断初始化 set_vector_handler(PIT0_ ...

随机推荐

  1. java课后实验性问题7

    1.异常处理 import javax.swing.*; class AboutException { public static void main(String[] a) { int i = 1, ...

  2. SourceTree软件

      A free Git client for Windows and Mac SourceTree 是 Windows 和Mac OS X 下免费的 Git 和 Hg 客户端管理工具,同时也是Mer ...

  3. Golang开源项目

    谷歌官方维护了一个基于go语言的开源项目列表: https://github.com/golang/go/wiki/Projects 其中有非常多的优秀项目值得学习,有几百行代码适合新手阅读的项目,也 ...

  4. Apache Jmeter教程(一) - 入门

    一.下载Jmeter 登录官网Jmeter下载,得到压缩包jmeter-5.0.tgz,下载地址:http://jmeter.apache.org/download_jmeter.cgi. 二.安装 ...

  5. Debezium系列随笔

    0.Debezium简介 1.Run Debezium for Mysql in docker step by step 2.Run Debezium for SQLServer in docker ...

  6. 最新 房多多java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.房多多等10家互联网公司的校招Offer,因为某些自身原因最终选择了房多多.6.7月主要是做系统复习.项目复盘.LeetCo ...

  7. 简单深入Joomla!3.1.5模块_组件开发(一)

    简单深入Joomla!3.1.5模块_组件开发 主要内容: 1, 模块(访问数据库,链接到组件,数据基本流向) 2, 组件CRUD(MVC模式,访问数据库,表单提交,AJAX提交,数据基本流向) 3, ...

  8. HDU6739 Invoker 【dp】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6739 借鉴了这个网址的题解:https://blog.csdn.net/qq_41785863/art ...

  9. DS博客大作业--树(李天明组)

    DS博客大作业--树 大作业博客要求 (10分) 1.树的存储结构说明 .树采用的是链式存储结构. .这段代码中定义了两个结构体.第一个是自定义为Name类型的结构体,里面的成员有字符串str和类型为 ...

  10. 飞腾PC机器与奔腾G645的PC机器以及E5-2630V4虚拟机内存性能简单对比

    1. 对比工具 sysbench 2. 对比命令 sysbench --test=memory --memory-total-size=12G --num-threads= run 3 安装方式 #u ...