zoukankan      html  css  js  c++  java
  • Scala学习十五——注解

    一.本章要点

    • 可以为类、方法、字段、局部变量、参数、表达式、类型参数以及各种类型定义添加注解
    • 对于表达式和类型,注解跟在被注解的条目之后
    • 注解的形式有@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注解会取消与型变相关的错误提示。。。  

    九.练习

  • 相关阅读:
    Encryption (hard) CodeForces
    cf 1163D Mysterious Code (字符串, dp)
    AC日记——大整数的因子 openjudge 1.6 13
    AC日记——计算2的N次方 openjudge 1.6 12
    Ac日记——大整数减法 openjudge 1.6 11
    AC日记——大整数加法 openjudge 1.6 10
    AC日记——组合数问题 落谷 P2822 noip2016day2T1
    AC日记——向量点积计算 openjudge 1.6 09
    AC日记——石头剪刀布 openjudge 1.6 08
    AC日记——有趣的跳跃 openjudge 1.6 07
  • 原文地址:https://www.cnblogs.com/lyq-biu/p/11975971.html
Copyright © 2011-2022 走看看