概念
Java有五个元注解,自动继承java.lang.annotation.Annotation。
什么是元注解,可以理解为其他普通注解进行解释说明
@Target 该注解的使用范围,限定应用场景。枚举类 ElemenetType 中
TYPE:类,接口
FIELD:字段,枚举的常量
METHOD:函数(方法)
PARAMETER:参数
CONSTRUCTOR:构造函数
ANNOTATION_TYPE:注解类型
LOCAL_VARIABLE:局部变量
PACKAGE:包
@Retention该注解的生存周期,相当于时间戳。枚举类型 RetentionPolicy 中
SOURCE:在源文件中有效,编译后会被丢弃(如@Override,@Deprecated)
CLASS:在class文件中有效,在jvm丢弃
RUNTIME:在运行时有效,class文件保留,jvm运行时保留(很多框架运用反射调用)
@Documented
javadoc文档生成工具的使用
@Inherited
允许子类继承父类中的注解。
@Repeatable
同一种注解可多次使用
作用
注释,解释,通过代码的标识元数据生成doc文档;
使用反射,通过代码标识的元数据对代码进行分析;
编译检查,通过代码标识的元数据让编译器进行基本检查。
实例
定义一个普通的注解,
public @interfaceTest
{
}
使用我们自定义的注解
@Testpublic classPerson
{
@TestprivateString name;
@Testprivate intage;
@Testpublic voidsay()
{
System.out.println("Hello,Java Annotation");
}
}
@Target(ElementType.PACKAGE) 注解作用的目标>包
这个注解要理解什么是友好声明类和包常量,包中有很多的内部访问的类或常量,就可以统一的放到友好声明类中,这样就方便,而且集中管理,减少friendly类到处游走的情况。
importjava.lang.annotation.ElementType;@Target(ElementType.PACKAGE)public @interfaceTest
{
}
@Testpackagetest;classPerson
{privateString name;private intage;public voidsay()
{
System.out.println("Hello,Java Annotation");
}
}
@Target(ElementType.CONSTRUCTOR) 注解作用的目标>构造函数
packagetest;importjava.lang.annotation.ElementType;importjava.lang.annotation.Target;
@Target(ElementType.CONSTRUCTOR)public @interfaceTest
{
}
packagetest;public classPerson
{privateString name;private intage;
@TestpublicPerson()
{
}public voidsay()
{
System.out.println("Hello,Java Annotation");
}
}
其他范围就不一一列举,都是相同的。
@Retention(RetentionPolicy.RUNTIME) 生存周期
代码运行时动态获取注解的信息
packagetest;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;
@Target(ElementType.CONSTRUCTOR)
@Retention(RetentionPolicy.RUNTIME)public @interfaceTest
{
}
packagetest;public classPerson
{privateString name;private intage;
@TestpublicPerson()
{
}public voidsay()
{
System.out.println("Hello,Java Annotation");
}
}
注解的属性-->成员变量
方法名是成员变量的的名字,变量的类型是他的返回值。
package test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)public@interface Test
{public int age() default 20;public String name() default "";publicString className();
}
packagetest;importjava.lang.annotation.Annotation;importjava.lang.reflect.Field;importjava.lang.reflect.Method;
@Test(age= 15,name = "zhangsan",className = "高三(3)班")public classPerson
{privateString name;private intage;publicPerson()
{
}private voidsay()
{
System.out.println("Hello,Java Annotation");
}
}
既然给了注解,我们要做的工作必然是要提取注解上面的内容,要拿到这些注解就要用到反射。
packagetest;importjava.lang.annotation.Annotation;importjava.lang.reflect.Field;importjava.lang.reflect.Method;
@Test(age= 15,name = "zhangsan",className = "高三(3)班")public classPerson
{privateString name;private intage;publicPerson()
{
}private voidsay()
{
System.out.println("Hello,Java Annotation");
}public static voidmain(String[] args)
{boolean hasAnnotation = Person.class.isAnnotationPresent(Test.class);if(hasAnnotation)
{
Test test= Person.class.getAnnotation(Test.class);
System.out.println("age:" +test.age());
System.out.println("name:" +test.name());
System.out.println("className:" +test.className());
}
}
}
输出结果
age:15name:zhangsan
className:高三(3)班
对于类的属性和方法,都是同样的道理。
成员注解
packagetest;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)public @interfaceField
{publicString name();
}
函数注解
packagetest;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)public @interfaceMethod
{publicString say();
}
Person类
packagetest;importjava.lang.annotation.Annotation;
@Test(age= 15,name = "zhangsan",className = "高三(3)班")public classPerson
{
@Field(name= "lisi")privateString name;private intage;publicPerson()
{
}
@Method(say= "hello")private voidsay()
{
System.out.println("Hello,Java Annotation");
}public static voidmain(String[] args)
{boolean hasAnnotation = Person.class.isAnnotationPresent(Test.class);if(hasAnnotation)
{
Test test= Person.class.getAnnotation(Test.class);
System.out.println("age:" +test.age());
System.out.println("name:" +test.name());
System.out.println("className:" +test.className());
}try{
java.lang.reflect.Field field= Person.class.getDeclaredField("name");
field.setAccessible(true);
Field check= field.getAnnotation(Field.class);if (check != null)
{
System.out.println("check value:" +check.name());
}
java.lang.reflect.Method method= Person.class.getDeclaredMethod("say");if (method != null)
{
Annotation[] ans=method.getAnnotations();for (int i = 0; i < ans.length; i++)
{
System.out.println("method annotation:" +ans[i].annotationType().getSimpleName());
}
}
}catch(NoSuchFieldException e)
{
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
}
}
输出
age:15name:zhangsan
className:高三(3)班
check value:lisi
method annotation:Method
可以看出我们获取了注解上的值,现在都没有实际意义,我们可以用注解来做些什么?
这些我没办法给出确切答案,只能说根据各人需求去合理利用注解。
实例
注解参数赋值
@Test注解
packagetest;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})public @interfaceTest
{
String value();
}
Person类属性赋值
packagetest;importorg.apache.poi.ss.formula.functions.T;importjava.lang.annotation.Annotation;importjava.lang.reflect.Field;importjava.lang.reflect.Method;public classPerson
{
@Test("zhangsan")privateString name;
@Test("15")private intage;publicPerson()
{
}private voidsay()
{
System.out.println("Hello,Java Annotation");
}
@OverridepublicString toString()
{return "name = " + name + "\n" + "age = " +age;
}public static voidmain(String[] args)
{
Person person= newPerson();try{//取得成员变量的值
Field field = Person.class.getDeclaredField("name");//打开权限
field.setAccessible(true);//判断属性是否有注解
if (field.isAnnotationPresent(Test.class))
{//获取属性上的注解值
Test test = field.getAnnotation(Test.class);
String name=test.value();//赋值
field.set(person,name);
}
Field field1= Person.class.getDeclaredField("age");
field1.setAccessible(true);if (field1.isAnnotationPresent(Test.class))
{
Test test= field1.getAnnotation(Test.class);int age =Integer.valueOf(test.value());
field1.set(person,age);
}
System.out.println(person);
}catch(Exception e)
{
e.printStackTrace();
}
}
}
输出
name =zhangsan
age= 15
用注解去检查函数等等。。
lz不善于用语言表达,所以可能有很多人没看懂,可以看下
一个大佬讲解的注解说明(简单易懂)