目录
1.声明注解
注解声明为@interface(注:这与interface接口没有任何关系)
内部定义成员通常用value表示
使用
可以指定成员的默认值,使用default定义
介绍
2.JDK中的元注解
@Retention:
@Target:
@Documented:
@Inherited:
3.JDK8中注解的新特性
可重复注解
测试重复定义注解
类型注解
4.使用注解
5.示例-反射获取注解
先定义一个注解:
通过反射获取注解
6.示例使用场景
7.通过反射获取类中所有加了注解的方法、变量-示例
1.声明注解
注解声明为@interface(注:这与interface接口没有任何关系)
public @interface MyAnnotation {
}
内部定义成员通常用value表示
public @interface MyAnnotation {String value();
}
使用
@MyAnnotation(value = "Hello")public int add(int a, int b){return a + b;
}
可以指定成员的默认值,使用default定义
public @interface MyAnnotation {String value() default "Hello";
}
介绍
- 如果自定义注解没有成员,表明是一个标识;如果注解有成员,在使用注解时必须指定成员的值。
- 定义新的注解类型使用@interface
- 自定义注解自动继承java.lang.annotation.Annotation接口
- 注解的成员变量类型可以是8中基本数据类型、String类型、Class类型、Enum类型、Annotation类型或以上类型的数组。
- 自定义注解必须配上注解的信息处理流程(使用反射)才有意义
2.JDK中的元注解
元注解用于修饰其他Annotation的定义,它是对现有的注解进行解释说明的注解。
4个元注解:@Retention、@Target、@Documented、@Inherited
@Retention:
表示需要在什么级别保存该注释信息,用于描述注解的生命周期。
进入@Retention注解源码看到它只有一个RetentionPolicy类型的成员。
到,他是一个枚举类型,包括三个值(SOURCE、CLASS、RUNTIME)。
- RetentionPolicy.SOURCE:在源文件中有效,编译器直接丢弃这种策略的注释。
- RetentionPolicy.CLASS:在class文件中有效,当运行java程序时,JVM不会保留注释。
- RetentionPolicy.RUNTIME:在运行时有效,当运行java程序时,JVM会保留注释。程序可以通过反射获取该注释。
@Target:
用于描述注解的适用范围(即可以用在什么地方)
进入@Target注解源码看到它只有一个ElementType数组类型的成员。
public enum ElementType {
TYPE,
FIELD,
METHOD,
PARAMETER,
CONSTRUCTOR,
LOCAL_VARIABLE,
ANNOTATION_TYPE,
PACKAGE,
TYPE_PARAMETER,
TYPE_USE
}
@Documented:
说明该注解将被包含在javadoc中
@Inherited:
说明子类可以继承父类中的该注解
3.JDK8中注解的新特性
可重复注解
如果我们需要定义重复注解,就必须给它定义容器类,还要使用 @Repeatable 注解修饰。
@Repeatable(MyAnnotations.class)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {String value() default "hello";}/*** 容器类*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotations {RepetitionAnnotation[] value();}
测试重复定义注解
public class AnnotationTest {/*** @Description 获取指定两个数之和* @param a* @param b* @return 两数之和*/@MyAnnotation(value = "Hello")@MyAnnotation(value = "你好")public int add(int a, int b){return a + b;}
}
类型注解
- 向 @Target 中添加两种类型 TYPE_PARAMETER和TYPE_USE
4.使用注解
@Target(value= {ElementType.TYPE,ElementType.METHOD})
@Documented
@Retention(value= RetentionPolicy.RUNTIME)
@Inherited
@interface myAnnotation{String name() default "9999";
}
@myAnnotation(name="sssss")
static class as9{@myAnnotation(name="ss9")public void ss(){}public void cc() throws NoSuchMethodException {as9.class.getAnnotation(myAnnotation.class).name();}
}
@myAnnotation()
static class as6{
}@Test
public void t17() throws Exception {System.out.println(as9.class.getAnnotation(myAnnotation.class).name());//sssssSystem.out.println(as6.class.getAnnotation(myAnnotation.class).name());//sssssSystem.out.println(as9.class.getMethod("ss",null).getAnnotation(myAnnotation.class).name());//获取方法上的注解值
}
5.示例-反射获取注解
先定义一个注解:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyField {String description();int length();
}
通过反射获取注解
public class MyFieldTest {//使用我们的自定义注解@MyField(description = "用户名", length = 12)private String username;@Testpublic void testMyField(){// 获取类模板Class c = MyFieldTest.class;// 获取所有字段for(Field f : c.getDeclaredFields()){// 判断这个字段是否有MyField注解if(f.isAnnotationPresent(MyField.class)){MyField annotation = f.getAnnotation(MyField.class);System.out.println("字段:[" + f.getName() + "], 描述:[" + annotation.description() + "], 长度:[" + annotation.length() +"]");}}}
}
6.示例使用场景
- 自定义注解+拦截器 实现登录校验
- 自定义注解+AOP 实现日志打印
7.通过反射获取类中所有加了注解的方法、变量-示例
@Target(value= {ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Documented
@Retention(value= RetentionPolicy.RUNTIME)
@Inherited
@interface myAnnotation{String name() default "9999";
}
@myAnnotation(name="sssss")
static class as9{@myAnnotation(name="ss9")public void ss(){}@myAnnotation(name="ss92")public void ss2(){}@myAnnotation(name="ss929")private String cc;
}
@myAnnotation()
static class as6{
}@Test
public void t17() throws Exception {System.out.println(as9.class.getAnnotation(myAnnotation.class).name());//sssssSystem.out.println(as6.class.getAnnotation(myAnnotation.class).name());//sssssSystem.out.println(as9.class.getMethod("ss",null).getAnnotation(myAnnotation.class).name());Class c = as9.class;for (Field f:c.getDeclaredFields()){//反射获取所有字段if(f.isAnnotationPresent(myAnnotation.class)){myAnnotation my = f.getAnnotation(myAnnotation.class);System.out.println("字段:[" + f.getName() + "], 值:[" + my.name() + "]");}}for (Method f:c.getDeclaredMethods()){//获取所有方法if(f.isAnnotationPresent(myAnnotation.class)){myAnnotation my = f.getAnnotation(myAnnotation.class);System.out.println("方法名:[" + f.getName() + "], 值:[" + my.name() + "]");}}}
ok
持续更新