本文共 7060 字,大约阅读时间需要 23 分钟。
一.介绍
二.java提供的5个基本的Annotation的使(定义在java.lang包下)
1.@Override2.@Deprecated
3.@SuppressWarnings
4.@SafeVarargs
堆污染警告5.@Functionalinterface
三.JDK的元Annotation(定义在java.lang.annotation下)
JDK还提供了6个Meta Annotation(元Annotation),其中有5个元Annotation用于修饰其他Annotation的定义(定义或自定义Annotation时)。其中@Repeatable专门用于定义java8新增的重复注解1.@Retention
2.@Target
3.@Documented
4.@Inherited
四.自定义Annotation
1.分类方法名称为了成员名,而方法返回值称为了成员的类型。而方法返回值必须为primitive类型、Class类型、枚举类型、Annotation类型或者由前面类型之一作为元素的一位数组。方法的后面可以使用default和一个默认数值来申明成员的默认值,null不能作为成员的默认值
2.标记Annotation
package com.tiglle.annotation;//使用@interface关键字定义Annotationpublic @interface Test {}
使用
package com.tiglle.test;import com.tiglle.annotation.Test;//使用在类上@Test public class UseTest { //使用在字段上 @Test private String name; //使用在方法上 @Test public void test(){ } //使用在方法上 @Test public void test(String name){ }}
3.元数据Annotation
package com.tiglle.annotation;public @interface MyAnnotation1 { //定义成员变量 //格式:返回值 方法名(); String name(); int age(); //定义了没有默认值的成员变量的Annotation使用时必须指定值}
使用
package com.tiglle.test;import com.tiglle.annotation.MyAnnotation1;//定义了没有默认值的成员变量的Annotation使用时必须指定值@MyAnnotation1(name="小明",age=20)public class UseMyAnnotation1 { //定义了没有默认值的成员变量的Annotation使用时必须指定值 @MyAnnotation1(name="小红",age=30) public void test(){}}
4.带默认值的元数据Annotation
package com.tiglle.annotation;public @interface MyAnnotation2 { //定义两个有初始默认值的成员变量 //格式:返回值 方法名() defalut 值; String name() default "小明"; int age() default 20; //指定了初始值的Annotation在使用时可以选择性的指定值,指定的值会覆盖初始值}
使用:
指定了初始值的Annotation在使用时可以选择性的指定值,指定的值会覆盖初始值package com.tiglle.test;import com.tiglle.annotation.MyAnnotation2;//指定了初始值的Annotation在使用时可以选择性的指定值,指定的值会覆盖初始值@MyAnnotation2public class UseAnnotation2 { //指定了初始值的Annotation在使用时可以选择性的指定值,指定的值会覆盖初始值 @MyAnnotation2(name="小明") public void test1(){} //指定了初始值的Annotation在使用时可以选择性的指定值,指定的值会覆盖初始值 @MyAnnotation2(age=20) public void test2(){} //指定了初始值的Annotation在使用时可以选择性的指定值,指定的值会覆盖初始值 @MyAnnotation2(name="小明",age=20) public void test3(){}}
五.提取Annotation信息(使Annotation生效)
1.通过反射获取程序中的Annotation信息,并做出相应的处理
2.通过反射操作Annotation的方法
3.获取某个方法的Annotation信息
@Retention(RetentionPolicy.RUNTIME):让注解可以保留到运行时 定义:package com.tiglle.annotation;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;//使用@interface关键字定义Annotation//@Retention(RetentionPolicy.RUNTIME):让注解可以保留到运行时,不然通过反射获取不到Annotation信息@Retention(RetentionPolicy.RUNTIME)public @interface Test {}
在UseTest类的test方法添加@Test的Annotation
获取方法Annotation信息package com.tiglle.opera;import java.lang.annotation.Annotation;import java.lang.reflect.Method;public class OperaUseTest { public static void main(String[] args) throws Exception{ //获取UseTest类的test方法的所有注解 Class clazz = Class.forName("com.tiglle.use.UseTest"); Method testMeth = clazz.getMethod("test"); Annotation[] annos = testMeth.getAnnotations(); for(Annotation anno:annos){ System.out.println(anno); } }}//运行结果:@com.tiglle.annotation.Test()
4.获取元数据Annotation的元数据信息
package com.tiglle.annotation;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;//@Retention(RetentionPolicy.RUNTIME):让注解可以保留到运行时@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation1 { //定义成员变量 //格式:返回值 方法名(); String name(); int age(); //定义了没有默认值的成员变量的Annotation使用时必须指定值}
有默认值的元数据Annotation
package com.tiglle.annotation;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;//@Retention(RetentionPolicy.RUNTIME):让注解可以保留到运行时@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation2 { //定义两个有初始默认值的成员变量 //格式:返回值 方法名() defalut 值; String name() default "小明"; int age() default 20; //指定了初始值的Annotation在使用时可以选择性的指定值,指定的值会覆盖初始值}
使用:
package com.tiglle.use;import com.tiglle.annotation.MyAnnotation1;import com.tiglle.annotation.MyAnnotation2;public class UseMyAnnotation { @MyAnnotation1(name="小红",age=90)//无默认值的 @MyAnnotation2//有默认值的 public void test(String name){ }}
获取元数据Annotation的元数据信息的操作
package com.tiglle.opera;import java.lang.annotation.Annotation;import java.lang.reflect.Method;import com.tiglle.annotation.MyAnnotation1;import com.tiglle.annotation.MyAnnotation2;public class OperaUseMyAnnotation { public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.tiglle.use.UseMyAnnotation"); Method testMeth = clazz.getMethod("test"); //获取test类的所有Annotation Annotation[] annos = testMeth.getAnnotations(); for(Annotation anno:annos){ //如果anno时MyAnnotation1类型 if(anno instanceof MyAnnotation1){ //将anno强转为MyAnnotation1类型 MyAnnotation1 myAnno1 = (MyAnnotation1) anno; //获取元数据信息 String name = myAnno1.name(); int age = myAnno1.age(); System.out.println("MyAnnotation1.name="+name+",MyAnnotation1.age="+age); } //如果anno时MyAnnotation2类型 if(anno instanceof MyAnnotation2){ //将anno强转为MyAnnotation2类型 MyAnnotation2 myAnno2 = (MyAnnotation2) anno; //获取元数据信息 String name = myAnno2.name(); int age = myAnno2.age(); System.out.println("MyAnnotation2.name="+name+",MyAnnotation2.age="+age); } } }}运行结果:MyAnnotation1.name=小红,MyAnnotation1.age=90MyAnnotation2.name=小明,MyAnnotation2.age=20
六.使用Annotation的示例
1.指定运行的方法(只运行一个程序添加了指定注解的方法) 自定义@Run注解(标记annotation)package com.tiglle.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;//@Retention(RetentionPolicy.RUNTIME):让注解可以保留到运行时//@Target(ElementType.METHOD):只能用在方法上面@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface Run {}
使用注解:
package com.tiglle.use;import com.tiglle.annotation.Test;//使用在类上@Test public class UseTest { //使用在字段上 @Test private String name; //使用在方法上 @Test public void test(){ } //使用在方法上 @Test public void test(String name){ }}
对使用注解的操作
package com.tiglle.opera;import java.lang.reflect.Method;import com.tiglle.annotation.Run;public class OperaUseRun { public static void main(String[] args) throws Exception { selectRun("com.tiglle.use.UseRun"); } /** * 根据类名判断有没有添加Run注解,有即运行改添加@Run注解的方法 * @param forName * @throws Exception */ public static void selectRun(String className) throws Exception{ Class clazz = Class.forName(className); //获取所有方法 Method[] meths = clazz.getMethods(); Object obj = clazz.newInstance(); for(Method meth:meths){ //如果方法使用了@Run注解 if(meth.isAnnotationPresent(Run.class)){ //即运行该方法(可能调用者不是同一个对象) meth.invoke(obj); } } }}运行结果:我是run1,添加了@Run注解我是run4,添加了@Run注解