本文共 4119 字,大约阅读时间需要 13 分钟。
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
对于注解的概念可简要概括为:
- JDK1.5之后的新特性
- 说明程序的
- 使用注解:@注解名称
关于注解的作用可以分为三类:
①编写文档:通过代码里标识的注解生成文档【生成doc文档】
②代码分析:通过代码里标识的注解对代码进行分析【使用反射】 ③编译检查:通过代码里标识的注解让编译器能够实现基本的编译【Override】
下面我为大家演示一下生成doc文档:
首先新建下面文件:/** * @author jackTan */public class JavaDocDemo { /** * @author jackTan * @param a 参数1 * @param b 参数2 * @return 获得a与b的和 */ public int getAdd(int a,int b){ return a+b; }}
来到该路径的命令行:
现在我们得到了doc文档。
- @Override :检测被该注解标注的方法是否是继承自父类(接口)的
- @Deprecated:该注解标注的内容,表示已过时
- @SuppressWarnings:压制警告, 一般传递参数all @SuppressWarnings(“all”)
演示:
未使用注解前,三条绿杠就是警告: 加入注解后警告消失: 当然把注解放在类前面那么所有的警告都消失.注解的格式是:
public @interface 注解名称{
属性列表; } 还是JavaDemoDoc.java文件,内容如下:
下面我们来探寻他的本质。
public @interface JavaDocDemo { }从上图我们得到:
Compiled from “JavaDocDemo.java”
public interface JavaDocDemo extends java.lang.annotation.Annotation { }
这说明注解的本质是一个继承了java.lang.annotation.Annotation的接口。
注解属性就是指注解的内容,这些内容其实就是抽象方法,只不过这些抽象方法的返回值只能是:
- 基本数据类型(byte,int,short,long,float,double,boolean,char)
- String
- 枚举
- 注解
- 以上类型的数组
还有一个要求就是在使用属性时要对属性赋值。(但是如果是有默认值可以不赋值。)
下面我们来对上面的内容做一个演示:
/** * @author jackTan */public @interface JavaDocDemo { myAnno show1(); myAnno[] show1_(); String show2(); String[] show2_(); myEnum show3(); myEnum[] show3_(); int show4(); int[] show4_();}/** * @author jackTan */@interface myAnno{ }enum myEnum{ }
下面我们只保留继续演示:
int show4();
由于没有默认值,我们要给show4赋值。
@JavaDocDemo(show4 = 1)class TestAnno{ }
改为如下:
int show4() default 1;
这个时候有默认值,故而可以不赋值:
@JavaDocDemo()class TestAnno{ }
然后我们再来演示一下数组赋值:
public @interface JavaDocDemo { String[] show2_(); String[] show2();}//赋多个值要包上{},如果只有一个值可以省略{}@JavaDocDemo(show2_ = { "a","b","c"},show2="a")class TestAnno{ }
接下来要说一个特别的情况就是如果方法名叫做value并且只有他需要赋值,那么我们可以直接写值不写名。
把show方法改为:int value();
那么这个时候:
@JavaDocDemo(1)class TestAnno{ }
但是当不只有他一个要赋值呢?
public @interface JavaDocDemo { int value(); myAnno show1();}
这时必须写上value
@JavaDocDemo(value = 1,show1 = @myAnno)class TestAnno{ }
元注解是用于描述注解的注解。
1.@Target:描述注解能够作用的位置 他的取值为枚举类型ElementType的成员。//表示@JavaDocDemo只可以作用在类上@Target(ElementType.TYPE)public @interface JavaDocDemo { String[] show2_(); String[] show2();}@JavaDocDemo(show2_ = { "a","b","c"},show2="a")class TestAnno{ }
//表示@JavaDocDemo只可以作用在方法上@Target(ElementType.METHOD)public @interface JavaDocDemo { String[] show2_(); String[] show2();}class TestAnno{ @JavaDocDemo(show2_ = { "a","b","c"},show2="a") void get(){ }}
//表示@JavaDocDemo只可以作用在成员变量上@Target(ElementType.FIELD)public @interface JavaDocDemo { String[] show2_(); String[] show2();}class TestAnno{ @JavaDocDemo(show2_ = { "a","b","c"},show2="a") int i;}
还有些其他的读者自行尝试。
2.@Retention:描述注解被保留的阶段@Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
3.@Documented:描述注解是否被抽取到api文档中
被@Documented修饰的注解,在生成doc文档时会写出来,否则没有。 4.@Inherited:描述注解是否被子类继承 被@Inherited修饰的注解(假设我们叫A),如果@A修饰类,当该类作为父类被继承时,子类也被@A修饰。这一部分需要用到反射,这里举个案例就明白了。
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * @author jackTan */@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface JavaDocDemo { String method(); String type();}
/** * @author jackTan */@JavaDocDemo(method = "xxx" ,type = "int")public class MainTest { public static void main(String[] args) throws ClassNotFoundException { ClasstestAnnoClass = MainTest.class; JavaDocDemo annotation = testAnnoClass.getAnnotation(JavaDocDemo.class); System.out.println(annotation); System.out.println(annotation.method()+" "+annotation.type()); }}
那么这里我要着重来强调一下就是一定要指明@Retention(RetentionPolicy.RUNTIME),否则使用getAnnotation()获取到的是null,同时注意包,千万别搞错了,因为在其他包下面也有同名的注解和类
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
转载地址:http://ftlzi.baihongyu.com/