注解----2
注解的基本知识 Java内建注解
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
1. 注解的基本知识
1). 注解的工作方式
(1). java.lang.annotation.Annotation接口
[1]. 源码:
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extendsAnnotation> annotationType();
}
[2]. 所有的注解类型都继承了java.lang.annotation.Annotation这个公共接口 (接口的继承性)
【结论】说的是所有注解类型继承而不是实现,说明所有注解的类型本质就是接口
[3]【注意】手动为一个接口继承java.lang.annotation.Annotation这个公共接口是不能定义注解类型的类型。
换句话说,自定义注解并不是 public interfaceextends java.lang.annotation.Annotation{…}
(2). 注解的工作方式
[1]. 所有注解的类型实质都是接口
[2]. 程序可以通过反射获取指定程序元素中具有生命周期维持到内存字节码阶段的注解对象。
[3]. 注解能为程序元素设置元数据
{1}. 注解不影响程序代码的执行。无论是增加或者删除注解,代码都始终如一执行。
{2}. ****如果希望注解在程序运行的时候起到一定作用,则需要通过反射获取到指定程序中相应的注解对象 (一种标记),获取到指定的标记之后,在根据这种注解 (标记)来作相应的处理***
2).注解的使用
(1). 使用注解的语法
[1]. 使用注解的时候,需要在注解名前面加上一个@符号,并将注解作为修饰符来使用。
【修饰符】比如:类的修饰有public/default,方法的修饰符 pubic static finalsynchronized等
所以,注解使用起来,也可以像这些程序元素的修饰符一样来使用。
[2]. 注解使用的格式
“@”+注解名+ “(”+多个以逗号分隔的“name=value”键值对+“)”
如果注解中没有成员变量,那么注解名之后的部分就可以省略。
(2). 使用注解的注意事项和规范
[1]. 注解规范:注解以所修饰程序元素的修饰符的身份出现,要放在所修饰的程序元素其他修饰符的最前面。
不放在最前面,也不会报错
[2]. 注解规范:通常单独放置在一行
[3]. 默认情况下,注解可以修饰程序中的任何元素。如果想改变,可以通过@Target来修饰这个注解并规定这个注解的作用范围。
[4]. 一个程序元素不能被同一个注解的多个实例同时修饰,编译会报错。
e.g.
2. Java内建注解
内建注解位于java.lang包下面【不用导包】
1). @Override
(1). 源码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
(2). 作用
[1]. 生命周期:持续到java源文件阶段。编译之后,javac就会抛弃@Overrider注解
[2]. 作用范围:只能修饰的程序元素就是方法
【@Override作用】在需要重写父类方法的子类方法前面打上@Override注解,会提示开发者要重写这个父类的方法发生书写上的错误,@Override就会通过javac提示开发者父类没有这个可以重写的方法,这样就能避免子类重写父类方法因为笔误而导致没有真实覆盖父类的方法。
【注意】
{1}. @Override没有成员变量。
{2}. 由于@Override没有被@Documented修饰,所以,@Override这个注解不能被javadoc工具识别
2). @Deprecated
(1). 源码
package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
//由于使用了静态导入,所以Target的枚举成员常量可以不用书写类名
@Target(value={CONSTRUCTOR,FIELD, LOCAL_VARIABLE,METHOD, PACKAGE,PARAMETER, TYPE})
public @interface Deprecated {
}
(2). 作用
[1]. 生命周期:持续到内存字节码阶段。程序可以使用反射访问到@Deprecated该注解对象。
【为什么不是SOURCE阶段】一般获得到的别人的程序不是源文件,都是class文件。所以要告诉使用这个class文件的人这个方法过时了,必须将这个@Deprecated标记保存到至少到CLASS阶段。否则,如果仅仅保存到SOURCE阶段的话,当提供jar包的人一旦完成对源程序的编译之后,@Deprecatd就会被javac从源程序中抹去,无法保存到class文件中。这样,调用者调用本来是发行者认为过时的方法,也不会出现删除线这样的提示。所以@Deprecated的生命周期至少到CLASS阶段才能发挥应有的作用。
[2]. 作用范围:能修饰规定的所有八种程序元素
【注意】虽然@Target的value取值没有直接写出ANNOTATION_TYPE这个类型,但是TYPE取值是包含ANNOTATION_TYPE类型的。因此不用重复添加
[3]. 可以被javadoc工具识别
【@Deprecated作用】表示所修饰的程序元素已经过时,此时javac将在eclipse工具中在这个程序元素中打上下划线表示不推荐这个过时的程序元素的使用。
【注意】
{1}. @Deprecated没有成员变量。
{2}. JDK5的新注解
3). @SuppressWarnings
(1). 源码
package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
//由于使用了静态导入,所以Target的枚举成员常量可以不用书写类名
@Target({TYPE,FIELD, METHOD,PARAMETER, CONSTRUCTOR,LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
(2). 作用
[1]. 生命周期:持续到java源文件阶段。编译之后,javac就会抛弃@Overrider注解。
[2]. 作用范围:除了包PACKAGE以外,剩下的程序元素都能被@SuppressWarnings修饰。
[3]. 不可以被javadoc工具识别
【@SuppressWarnings作用】抑制javac产生警告注释 (通常说的报黄)。
[4]. @SuppressWarnings有一个String数组类型的属性变量
当@SuppressWarnings成员变量value取值是下面的值时候,javac取消代码警告
{1}. "deprecation":使用了过时元素
{2}. "unchecked":执行了未检查的转换 比如,没有使用泛型
{3}. "unused":有程序元素从未被使用
{4}. "fall through":switch..case中没有使用break语句使得从一种case情况通往下一种case情况
{5}. "path":在类路径或者源文件路径等中有不存在的路径
{6}. "serial":在可序列化的类上缺少serial Version UID定义
{7}. "finally":不能正常完成的finally子块
{8}. "all":上述情况的并集
5). 三种内建注解的相似性
(1). 三种内建注解都被@Retention和@Target来修饰
@Deprecated又被@Documented修饰,可以被javadoc来是识别
(2). 三种内建注解的特性
| @Documented修饰 | @Retention修饰 | @Target修饰 | 属性名 | 属性数据类型 |
@Overried | —— | SOURCE | METHOD | —— | —— |
@Deprecated | 可以被javadoc识别 | RUNTIME | 所有类型 | —— | —— |
@SuppressWarnings | —— | SOURCE | 除包以外的所有类型 | value | String[] String数组 |
[1]. 三种内建注解本身的生命周期只有@Deprecated被保留到内存字节码阶段,剩下全部是Java源文件阶段。
[2]. 只有@SuppressWarnings这个注解有一个value的属性变量,是字符串数组类型的。
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------