zoukankan      html  css  js  c++  java
  • 12.Scala- 注解

    第12章 注解

    注解就是标签。

    标签是用来标记某些代码需要特殊处理的。

    处理的手段可以在代码运行时操作,也可以在编译期操作。

    12.1 什么可以被注解

     1)  可以为类,方法,字段局部变量,参数,表达式,类型参数以及各种类型定义添加注解

    @Entity class Student
     
    @Test def play() {}
     
    @BeanProperty var username = _
     
    def doSomething(@NotNull message: String) {}
     
    @BeanProperty @Id var username = _

     2)  构造器注解,需要在主构造器之前,类名之后,且需要加括号,如果注解有参数,则写在注解括号里

    class Student @Inject() (var username: String, var password: String)

    3)  为表达式添加注解,在表达式后添加冒号

    (map1.get(key): @unchecked) match {...}

    4)  泛型添加注解

    class Student[@specialized T]

    5)  实际类型添加注解

    String @cps[Unit]

    12.2 注解参数

     Java注解可以有带名参数:

    @Test(timeout = 100, expected = classOf[IOException])
     
    // 如果参数名为value,则该名称可以直接略去。
     
    @Named("creds") var credentials: Credentials = _  // value参数的值为 “creds”
     
    // 注解不带参数,圆括号可以省去
     
    @Entity class Credentials

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

    数值型的字面量,

    字符串,

    类字面量,

    Java枚举,

    其他注解。

    上述类型的数组(但不能是数组的数组)

    Scala注解可以是任何类型,但只有少数几个Scala注解利用了这个增加的灵活性。

    12.3 注解实现

    你可以实现自己的注解,但是更多的是使用Scala和Java提供的注解。

        注解必须扩展Annotation特质

    class unchecked extends annotation.Annotation

    12.4 针对 java 特性的注解

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

    @volatile var done = false  // JVM中将成为volatile的字段
     
    @transient var recentLookups = new HashMap[String, String]  // 在JVM中将成为transient字段,该字段不会被序列化。
     
    @strictfp def calculate(x: Double) = ...
     
    @native def win32RegKeys(root: Int, path: String): Array[String]
     

     2)  标记接口:Scala用注解@cloneable和@remote 而不是 Cloneable和Java.rmi.Remote“标记接口”来标记可被克隆的对象和远程的对象。

    @cloneable class Employee

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

    class Book {
     
    @throws (classOf[IOException]) def read(filename: String) { ... }
     
    ...
     
    }
     
    Java版本的方法签名:
     
    void read(String fileName) throws IOException
     
    // 如果没有@throws注解,Java代码将不能捕获该异常
     
    try {//Java代码
     
    book.read("war-and-peace.txt");
     
    } catch (IOException ex) {
     
    ...
     
    }
     

    即:Java编译期需要在编译时就知道read方法可以抛IOException异常,否则Java会拒绝捕获该异常。

    12.5 用于优化的注解

    尾递归的优化

    啥玩是尾递归?

    尾递归:

    def story(): Unit = {从前有座山,山上有座庙,庙里有个老和尚,一天老和尚对小和尚讲故事:story()}

    尖叫提示:进入下一个函数不再需要上一个函数的环境了,得出结果以后直接返回。

    非尾递归:

    def story(): Unit =  {从前有座山,山上有座庙,庙里有个老和尚,一天老和尚对小和尚讲故事:story(),小和尚听了,找了块豆腐撞死了}

    尖叫提示:下一个函数结束以后此函数还有后续,所以必须保存本身的环境以供处理返回值。

    递归调用有时候能被转化成循环,这样能节约栈空间:

    object Util {
     
      def sum(xs: Seq[Int]): BigInt = {
        if (xs.isEmpty) 0 else xs.head + sum(xs.tail)
      }
      ...
    }
     

    上面的sum方法无法被优化,因为计算过程中最后一步是加法,而不是递归调用。调整后的代码:

    def sum2(xs: Seq[Int], partial: BigInt): BigInt = {
     
      if (xs.isEmpty) partial else sum2(xs.tail, xs.head + partial)
     
    }

     Scala编译器会自动对sum2应用“尾递归”优化。如果你调用sum(1 to 1000000) 将会发生一个栈溢出错误。不过sum2(1 to 1000000, 0) 将会得到正确的结果。

    尽管Scala编译器会尝试使用尾递归优化,但有时候某些不太明显的原因会造成它无法这样做。如果你想编译器无法进行优化时报错,则应该给你的方法加上@tailrec注解。

           尖叫提示:对于消除递归,一个更加通用的机制叫做“蹦床”。蹦床的实现会执行一个循环,不停的调用函数。每个函数都返回下一个将被调用的函数。尾递归在这里是一个特例,每个函数都返回它自己。Scala有一个名为TailCalls的工具对象,帮助我们轻松实现蹦床:

    import scala.util.control.TailCalls._
     
    def evenLength(xs: Seq[Int]): TailRec[Boolean] = {
     
      if(xs.isEmpty) done(true) else tailcall(oddLength(xs.tail))
     
    }
     
     
     
    def oddLength(xs: Seq[Int]): TailRec[Boolean] = {
     
      if(xs.isEmpty) done(false) else tailcall(evenLength(xs.tail))
     
    }
     
    // 获得TailRec对象获取最终结果,可以用result方法
     
    evenLength(1 to 1000000).result
     
     
     
  • 相关阅读:
    基于C++ Qt实现的红色警戒3修改器
    Java多线程(十五):CountDownLatch,Semaphore,Exchanger,CyclicBarrier,Callable和Future
    Java多线程(十四):Timer
    Java多线程(十三):线程池
    Java多线程(十二):中断机制
    Java多线程(十一):线程组
    Java多线程(十):BlockingQueue实现生产者消费者模型
    德国语言+留学签证递交材料详解(上海)
    Java多线程(九):生产者消费者模型
    Java多线程(八):ReentrantReadWriteLock
  • 原文地址:https://www.cnblogs.com/LXL616/p/11132747.html
Copyright © 2011-2022 走看看