Scala 自学笔记 注解
2015-03-13 10:47
281 查看
注解
什么可以被注解
注解参数
注解实现
Java修饰符
标记接口
受检异常
变长参数
JavaBeans
用于优化的注解
尾递归
跳转表生成与内联
可省略方法
基本类型的特殊化
用于错误和警告的注解
注解在Java中广泛使用,我们可以对Scala类使用Java注解 @Test (timeout = 100) def testSomeFeature(){...} @Entity class Credentials{ @Id @BeanProperty var username: String = _ @BeanProperty var password: String= _ } 除了@BeanProperty , 都是JUnit和JPA的注解,这量个Java框架并不知道我们用的是Scala。 我们也可以用Scala注解,这些注解会由Scala编译器或编译器插件处理。 Java注解并不影响编译器如何将源码编译成字节码,他们仅仅是往字节码中添加数据,以便外部工具可以利用它们。 而在Scala中,注解可以影响编译过程,比如@BeanProperty 注解可以触发getter和setter的生成。
什么可以被注解
像Java一样,可以为 类 方法 字段 局部变量 参数添加注解 @Entity class Credentials //类 @Test def testSomeFeature(){} //方法 @BeanProperty var username = _ //字段 def doSomething (@NotNull message: String){} // 参数 可以添加多个注解,先后次序无影响 @BeanProperty @Id var username = _ 给主构造器添加注解时,需要将注解放置在构造器之前,并加上一对圆括号(如果注解不带参数的话) class Credentials @Inject() (var username: String, var password: String) 为表达式添加注解,需要在表达式后加上冒号,然后是注解本身 (myMap.get(key) : @unchecked) match {...} //我们为表达式myMap.get(key)添加了注解 可以为类型参数添加注解 class MyContainer[@specialized T] 针对实际类型的注解应放置在类型名称之后, String @cps[Unit] // @cps带一个类型参数
注解参数
Java注解可以有带名参数, @Test(timeout = 100, expected = classOf[IOException]) 如果参数名为value,该名称可以省略 @Named("creds") var credentials: Credentials = _ //value参数的值为"creds" 如果注解不带参数,圆括号可以略去 @Entity class Credentials 大多数注解参数都有缺省值 @Test def test SomeFeature(){...} 等同于 @Test(timeout = 0, expected = classOf[org.junit.Test.None]) def test SomeFeature(){...} Java注解的参数类型,只能是 数值型的字面量 字符串 类字面量 Java枚举 其他注解 上述类型的数组(但不能是数组的数组) Scala注解的参数可以是任何类型
注解实现
注解必须扩展Annotation特质 class unchecked extends annotation.Annotation 注解类可以选择扩展StatcAnnotation 或 ClassfileAnnotation特质 前者在编译单元中可件,它将放置Scala特有的元数据到类文件中 后者的本意是在类文件中生成Java注解元数据,不过Scala2.9并未支持该特性。
Scala的构造器注解仅会被应用到参数自身,字段注解只能应用到字段 class Credentials(@NotNull @BeanProperty var username: String) 默认情况下,这里注解只作用到参数 那些由于Scala特性产生的,字段,取值器/改值器,getter/setter都不会影响。 元注解(注解的注解) @param @field @getter @setter @beanGetter @beanSetter使得注解被附在别处 @getter @setter @beanGetter @beanSetter class deprecated(message:String = "", since:String= "") extends annotation.StaticAnnotation //当前注解会被自动应用到相应的目标上 也可以临时根据需要应用这些元注解: @Entity class Credentials { @(Id @beanGetter) @BeanProperty var id = 0 }//@Id 注解被应用到Java的getId方法,这个JPA要求的方法。
Java修饰符
一些不常用的Java特性,Scala使用注解,而不是修饰符 @volatile注解 @volatile var done = false // 在JVM中将成为volatile的字段 可以被多个线程同时更新。 @transient注解 @transient var recentLookups = new HashMap[String,String] // 在JVM中为transient字段,非序列化的一部分,常用语临时保存的缓存数据,或易于重新计算的数据。 @strictfp注解, 对应Java的strictfp修饰符 @strictfp def calculate(x:Double) = ... 该方法使用IEEE的double值来进行浮点计算 而不是使用80位扩展精度(Intel处理器默认使用的实现) 计算结果会更慢,但代码可移植性更高。 @native注解,来标记那些在C C++中实现的方法,对应 Java的 native修饰符 @native def win32Regkeys(root: Int, path: String):Array[String]
标记接口
Scala用注解@cloneable和@remote ,代替Cloneable和java.rmi.Remote标记接口来标记可被克隆的和远程的对象 @cloneable class Employee 序列化 @SerialVersioinUID(43534534L) class Employee extends Person with Serializable
受检异常
@throws 由于Scala不检查受检异常,如果从Java代码中调用Scala方法,其签名应包含可能被抛出的受检异常 class Book{ @throws (classOf[IOException]) def read(filename: String) {...} } 转换到Java的签名为 viod read(String filename) throws IOException 如果没有@throws 注解,以下在Java中运行的代码会拒绝捕获该异常。 try{ // java code book.read("...") }catch(IOException ex){ }
变长参数
@varargs注解,从Java调用scala的带有变长参数的方法。 def process(args: String*) Scala编译器把变长参数翻译成序列 def process(args: Seq[String]) // 这样的签名在Java中使用起来比较麻烦 @varargs def process(args: String*) 编译器生成的Java代码 void process(String ... args) // java桥接方法
JavaBeans
class Person{ @BeanProperty var name : String = _ // 会产生setter和getter } @BooleanBeanProperty 生成带有is前缀的getter方法,用于Boolean.
用于优化的注解
尾递归
递归调用有时被转化为虚幻,这样能节省栈控件 obejct Utill{ def sum(xs: Seq[Int]:BigInt = if ( xs.isEmpty) 0 else xs.head + sum(xs.tail) // 该方法无法被优化,因为最后一步步是递归调用而是加法 } 修改后 def sum2(xs: Seq[Int], partial:BigInt) : BigInt = if(xs.isEmpty) partial else sum2( xs.tail, xs.head + partial) // 由于计算过程的最后一步是地柜调用同一个方法,因此可以被变换成调回到方法顶部的循环 //Scala编译器会自动将这个方法应用“尾递归”优化 sum( 1 to 1000000) // 栈溢出,压了太多方法栈 sum2( 1 to 1000000, 0) // 返回序列之和,方法被转化为一个循环 虽然编译器会常识使用尾递归优化,但某些不太明显的原因会造成它无法优化。 如果加@tailrec,当无法优化时会自动报错 class Util{ @tailrec def sum2(xs :Seq[Int], partial:BigInt): BigInt = .... } 程序编译会失败,提示错误:“could not optimize @tailrec annotated method sum2: it is neither private nor final so can be overriden” 在这种情况下,可以将方法挪到对象中,或将它声明为private或final
跳转表生成与内联
switch语句通常可以被编译成跳转表,这比一些列if/else表达式更加高效。 @switch注解让Scala的match语句是不是真的被编译成了跳转表 (n : @swith) match { case 0 => "Zero" case 1 => "One" case _ => "?" } 方法内联,将方法调用语句替换为被调用的方法体。 @inline,用来建议编译器做内联 @noinline,告诉编译器不要内联
可省略方法
@elidable(500) def dump(prop: Map[String, String]) { ... } 如果用如下命令编译 scalac -Xelide-below 800 myprop.scala //则上述方法不会别生成 elidable对象定义了很多常量 MAXIMUM 或 OFF = Int.MaxValue ASSERTION = 2000 SEVERE = 1000 WARNING = 900 INFO = 800 CONFIG = 700 FINE = 500 FINER = 400 FINEST = 300 MINIMUM 或 ALL = Int.MinValue 可以在注解中使用常量 import scala.annotation.elidable._ @elidable(FINE) def ... scalac -Xelide-below INFO myprog.scala 注:如果不指定-Xelide-below标志,低于1000的方法会被省略。 -Xelide-below OFF 省略所有方法 -Xelide-below ALL 什么都不要省略 Prede模块定义了可被忽略的assert方法 禁用断言 -Xelide-below 2001 或 -Xelide-below MAXIMUM 对被省略的方法调用,编译器会替换成Unit对象,如果使用了被省略方法的返回值,抛出ClassCastException 最好只对那么没有返回值的方法使用@elidable注解。
基本类型的特殊化
打包和解包基本类型的值是不高效的,特别是在泛型代码中 def different[T](x:T, y:T) = x!=y 如果调用 different(3, 4),每个整数值都被包装成一个java.lang.Integer。 def different[T](x:Int, y:Int) = x!=y // 不存在包装过程 再提供的七个重载方法,分别对应其他基本类型 @specialized注解,,让编译器自动生成这些方法 def different[@specialized T](x:Int, y:Int) = x!=y 可以将特殊化限定在所有可选类型的子集: def different[@specialized(Long, Double) T](x:Int, y:Int) = x!=y 在注解构造器中,可以指定如下类型的任意子集: Unit Boolean Byte Short Char Int Long Float Double
用于错误和警告的注解
@deprecated, 标注方法弃用 @deprecated(message= "..." , since = "...") def factorial(n : Int) : Int = ... @deprecatedName,标记弃用的参数名 def draw(@deprecatedName('sz) size :int) //这里的构造器阐述是一个单引号开头的名称 当调用draw(sz=12),会得到一个该名称已过时的警告 @implicitNodeFound,用于某个隐式参数不存在的时候生成有意义的错误提示 @unchecked , 用于在匹配不完整时,取消警告信息 (lst : @unchecked) match{ case head :: tail => ... } @uncheckedVariance , 取消与型变相关的错误提示 java.util.Comparator按理应该是 型变的 如果Student是Person的子类型,那么需要Comparator[Student]时,可以用Comparator[Person], 但Java泛型不支持型变 通过@uncheckedVariance来解决 trait Comparator [-T] extends java.lang.Comparator[T @uncheckedVariance]
相关文章推荐
- Jquery DataTables自学笔记 之 基本设置的中文注解
- Scala 自学笔记2_类
- Java自学笔记之Hibernate-常用的hibernate注解
- Jquery DataTables自学笔记 之 基本设置的中文注解
- Scala自学代码笔记
- Java自学笔记之Hibernate-用注解方式实现多对多
- Scala 自学笔记3_特质
- 黑马程序员自学笔记————通过反射来获取注解的信息;
- Scala 自学笔记 模式匹配和样例类
- Java自学笔记之Hibernate-常用的hibernate注解
- scala自学笔记(2)
- Scala 自学笔记
- Scala 自学笔记 集合
- scala学习笔记(十四) 注解
- Scala自学笔记
- Java自学笔记之Hibernate-用注解方式实现一对多单项
- Java自学笔记之Hibernate-用注解方式实现一对多双向关联
- scala 自学笔记 高阶函数
- scala自学笔记(1)
- Jquery DataTables自学笔记 之 基本设置的中文注解