JAVA注解
从本质上来说,注解是一种标签,其实质上可以视为一种特殊的注释,如果没有解析它的代码,它并不比普通注释强。
解析一个注解往往有两种形式:编译期直接的扫描,运行期的反射
注解的作用
编译器信息 - 编译器可以使用注解来检测错误或抑制警告。
编译时和部署时的处理 - 程序可以处理注解信息以生成代码,XML 文件等。
运行时处理 - 可以在运行时检查某些注解并处理。
(使用注解以减少配置文件或代码(xml,properties),是注解最大的用处。
注解的代价
显然,它是一种侵入式编程,那么,自然就存在着增加程序耦合度的问题。
自定义注解的处理需要在运行时,通过反射技术来获取属性。如果注解所修饰的元素是类的非 public 成员,也可以通过反射获取。这就违背了面向对象的封装性。
注解所产生的问题,相对而言,更难以 debug 或定位。
注解的应用范围
注解可以应用于类、字段、方法和其他程序元素的声明。
新的应用范围:
类实例初始化表达式:
new @Interned MyObject();
类型转换:
myString = (@NonNull String) str;
实现接口的声明:
class UnmodifiableList<T> implements
@Readonly List<@Readonly T> {}
抛出异常声明:
void monitorTemperature()
throws @Critical TemperatureException {}
内置注解
@Override 用于表明被修饰方法覆写了父类的方法。
@Deprecated 用于标明被修饰的类或类成员、类方法已经废弃、过时,不建议使用。
@SuppressWarnnings 用于关闭对类、方法、成员编译时产生的特定警告。
@SafeVarargs(JDK7 引入) 告诉编译器,在可变长参数中的泛型是类型安全的。可变长参数是使用数组存储的,而数组和泛型不能很好的混合使用。
@FunctionalInterface(JDK8 引入)用于指示被修饰的接口是函数式接口。
··函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式。
元注解
元注解的作用就是用于定义其它的注解。
@Retention 指明了注解的保留级别。
RetentionPolicy.SOURCE - 标记的注解仅在源文件中有效,编译器会忽略。
RetentionPolicy.CLASS - 标记的注解在 class 文件中有效,JVM 会忽略。
RetentionPolicy.RUNTIME - 标记的注解在运行时有效。
@Target
@Target 指定注解可以修饰的元素类型。
@Documented
表示无论何时使用指定的注解,都应使用 Javadoc(默认情况下,注释不包含在 Javadoc 中)。
@Inherited(JDK8 引入)
@Inherited 表示注解类型可以被继承(默认情况下不是这样)
@Repeatable(JDK8 引入)
@Repeatable 表示注解可以重复使用。
自定义注解
使用 @interface 自定义注解时,自动继承了 java.lang.annotation.Annotation 接口,由编译程序自动完成其他细节。
注解属性
注解属性的语法形式如下:
[访问级别修饰符] [数据类型] 名称() default 默认值;
注解处理器
java.lang.annotation.Annotation 是一个接口,程序可以通过反射来获取指定程序元素的注解对象,然后通过注解对象来获取注解里面的元数据。