更多Android架构进阶视频学习请点击:https://space.bilibili.com/474380680
本篇文章将从以下几个内容来阐述注解:
- [注解]
- [元注解]
- [自定义注解]
- [注解参数默认值]
一、注解(ANNOTATIONS)
注解将元信息(meta-information)与定义相关联。例如:方法前的注解 @deprecated
会造成编译器在该方法被调用时打印警告信息。
object DeprecationDemo extends App {
@deprecated
def hello = "hola"
hello
}
这个程序可以编译但是编译器会打印一句警告:“there was one deprecation warning”
。
注解子句适用于其后面的第一次定义或声明。一个以上的注解子句可以出现在定义和声明之前。这些子句的顺序并不重要。
1.1注解确保编码的正确性
如果有些条件不符合,某些注解可能会导致编译失败。例如,注解 @tailrec
确保方法是尾递归的(tail-recursive)。尾递归(Tail-recursion)可以确保内存需求保持不变。下面例子是如何在计算阶乘的方法中使用它:
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)
}
factorialHelper
方法有一个注解 @tailrec
用于确保方法的确是尾递归的(tail-recursive)。如果我们按照以下的方式改变 factorialHelper
的实现,它将会编译失败:
import scala.annotation.tailrec
def factorial(x: Int): Int = {
@tailrec
def factorialHelper(x: Int): Int = {
if (x == 1) 1 else x * factorialHelper(x - 1)
}
factorialHelper(x)
}
我们将获得提示信息:"Recursive call not in tail position"
。
1.2 影响代码生成的注释
一些类似 @inline
的注释会影响生成的代码(即你的 jar 文件可能相比不使用注解会有不同的字节数)。内联(Inlining)指在调用点的方法中插入代码。生成的字节码会更长,但希望运行的会更快点。使用注解 @inline
并不能确保方法将被内联,但是当且仅当满足生成代码块的一些启发性算法时,它将会触发编译器去进行内联操作。
1.3 Java 注解
在编译与 Java 互操作的 Scala 代码时,注解语法有一些不同之处值得注意:确保你在使用 Java 注解时使用 -target:jvm-1.8
选项。
Java 具有自定义元数据的注解形式。注解的一个关键特征是它们依赖特定的 name- value对 来初始化它们的元素。例如,如果我们需要一个注解来跟踪类的来源,我们可以将其定义为:
@interface Source {
public String URL();
public String mail();
}
然后按如下方式使用它
@Source(URL = "http://coders.com/",
mail = "[email protected]")
public class MyClass extends HisClass ...
Scala 中的注解应用程序看起来像是一个构造函数的调用,初始化 Java 注解必须使用命名参数:
@Source(URL = "http://coders.com/",
mail = "[email protected]")
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
元素是使用默认值指定的,因此我们不必明确为它提供一个值。但是,如果我们需要像下面这样做,我们就不能在 Java 中混淆这两种方式(明确名称和忽略名称):
@SourceURL(value = "http://coders.com/",
mail = "[email protected]")
public class MyClass extends HisClass ...
Scala 在这方面提供了更多地灵活性
@SourceURL("http://coders.com/",
mail = "[email protected]")
class MyScalaClass ...
二、元注解
java内置的注解有Override, Deprecated, SuppressWarnings等, 作用相信大家都知道.
现在查看Override注解的源码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
发现Override注解上面有两个注解, 这就是元注解. 元注解就是用来定义注解的注解.其作用就是定义注解的作用范围, 使用在什么元素上等等, 下面来详细介绍.
元注解共有四种@Retention, @Target, @Inherited, @Documented
-
@Retention 保留的范围,默认值为CLASS. 可选值有三种
- SOURCE, 只在源码中可用
- CLASS, 在源码和字节码中可用
- RUNTIME, 在源码,字节码,运行时均可用
@Target 可以用来修饰哪些程序元素,如 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER等,未标注则表示可修饰所有
@Inherited 是否可以被继承,默认为false
@Documented 是否会保存到 Javadoc 文档中
其中, @Retention是定义保留策略, 直接决定了我们用何种方式解析. SOUCE级别的注解是用来标记的, 比如Override, SuppressWarnings. 我们真正使用的类型是CLASS(编译时)和RUNTIME(运行时)
三、自定义注解
举个例子, 结合例子讲解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAnnotation {
String value();
String[] value2() default "value2";
}
元注解的的意义参考上面的讲解, 不再重复, 这里看注解值的写法:
类型 参数名() default 默认值;
其中默认值是可选的, 可以定义, 也可以不定义.
四、 默认参数值(DEFAULT PARAMETER VALUES)
Scala 提供了参数默认值功能,可以允许调用方省略那这些参数。
def log(message: String, level: String = "INFO") = println(s"$level: $message")
log("System starting") // prints INFO: System starting
log("User not found", "WARNING") // prints WARNING: User not found
该参数 level
有一个默认值,因此它是可选的。在最后一行,参数 "WARNING"
覆盖了默认参数 "INFO"
。在 Java 中可能执行重载方法的地方,你可以使用可选参数的方法来获得相同效果。但是,如果调用者省略一个参数,任何接下来的参数都必须被命名。
class Point(val x: Double = 0, val y: Double = 0)
val point1 = new Point(y = 1)
在这里我们必须要明确 y = 1
。
注意从 Java 代码里调用时, Scala 中的默认参数不是可选的。
// Point.scala
class Point(val x: Double = 0, val y: Double = 0)
// Main.java
public class Main {
public static void main(String[] args) {
Point point = new Point(1); // does not compile
}
}
更多Android架构进阶视频免费学习请点击:https://space.bilibili.com/474380680
参考:https://www.jianshu.com/p/a13c6326671d
https://blog.csdn.net/smile_from_2015/article/details/80345149