注解(Annotation)是在java 1.5开始引入的,它是java中很重要的一个知识点。现在使用的很多框架,例如:SpringBoot、Hibernate等都大量的使用了注解。
注释是元数据的一种形式,提供有关程序的数据,而不是程序本身的一部分。注解对它们所注解的代码的操作没有直接影响。它是Java中的一种特殊标记。
我们说注解的用途的前提是默认它是跟反射一起使用的,不然的话注解也就失去了它本来的作用了。注解有很多用途,比如:日志、权限、Spring中IOC等等都可以用注解来完成的。但是,总的来说有以下用途:
标准注解有10个,其中java.lang包下有5个分别是以下五个:
元注解也是java标准注解,只不过它们比较特殊,是作用在注解上的注解。元注解都在java.lang.annotation包下。
getAnnotation()
方法就能获取到父类中的注解。注解有5类,分别是:
@TestAnnotation(“测试”)
@TestAnnotation(owner=”公众号:索玛理”, value=”suncodernote”)
@Target(value = ElementType.TYPE_USE)
public @interface TypeAnnoDemo {
}
public class AnnotationTest {
public static void main(String[] args) {
@TypeAnnoDemo String string = "局部变量被类型注解注解";
type();
}
static @TypeAnnoDemo Integer type(){
System.out.println("返回值被类型注解注解");
return 0;
}
}
@Repeatable
注解进行修饰的注解。注解和接口的定义差不多,只不过注解多了个 「@」 符号。定义一个注解时有以下4点比较重要:
要自定义一个注解,有两个关键参数ElementType和RetentionPolicy必须要了解一下:
ElementType是一个枚举类型,它做为数组在@Target注解中出现。作用是对Java程序中注解可能出现的语法位置进行简单分类。
public enum ElementType {
TYPE,
FIELD,
METHOD,
PARAMETER,
CONSTRUCTOR,
LOCAL_VARIABLE,
ANNOTATION_TYPE,
PACKAGE,
TYPE_PARAMETER,
TYPE_USE
}
类型 | 可以应用的地方 |
---|---|
TYPE | 作用于类、接口(包括注解类型)或者枚举类 |
FIELD | 作用于属性 |
METHOD | 作用于声明的方法 |
PARAMETER | 作用于方法参数 |
CONSTRUCTOR | 作用于构造方法 |
LOCAL_VARIABLE | 作用于局部变量 |
ANNOTATION_TYPE | 作用于其他注解 |
PACKAGE | 作用于包 |
TYPE_PARAMETER | java 1.8引入的,作用于泛型参数 |
TYPE_USE | java 1.8引入的,作用于任何使用类型的地方 |
ElementType 中有些作用范围广的常量是可以替代其他常量的,就比如TYPE_USE可以可以替代PARAMETER 、LOCAL_VARIABLE 、FIELD等。
注解的保留策略,在注解@Retention
中声明,它表示要保留注解到哪种地步。
public enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE , ElementType.METHOD , ElementType.FIELD , ElementType.TYPE_PARAMETER, ElementType.LOCAL_VARIABLE , ElementType.PARAMETER , ElementType.TYPE_USE})
public @interface CustomAnnotation {
String name() default "";
/**
* 在某个地方只有某个ElementType能起作用
* @return
*/
ElementType type() default ElementType.TYPE;
/**
* 能多个ElementType在同一个地方起作用的数组
* @return
*/
ElementType[] types() default {};
}
@CustomAnnotation(types ={ElementType.TYPE_USE , ElementType.TYPE} )
public class AnnotationTest<@CustomAnnotation(name = "泛型参数" , types ={ElementType.TYPE_USE , ElementType.TYPE_PARAMETER} ) T> {
@CustomAnnotation(types ={ElementType.TYPE_USE , ElementType.FIELD})
private String field;
public static void main(String[] args) {
@CustomAnnotation(types ={ElementType.TYPE_USE , ElementType.PARAMETER}) String string = "局部变量被类型注解注解";
}
static @CustomAnnotation(types ={ElementType.TYPE_USE , ElementType.METHOD} ) Integer type(){
System.out.println("返回值被类型注解注解");
return 0;
}
@CustomAnnotation(type = ElementType.METHOD)
static void method(){
System.out.println("作用在方法");
}
static void param(@CustomAnnotation(types ={ElementType.TYPE_USE , ElementType.PARAMETER}) Integer p){}
}
在自定义注解@CustomAnnotation
中,将@Targe
t元注解中的ElementType.TYPE_PARAMETER
删除,测试类AnnotationTest
不会报错,但是如果把ElementType.TYPE_USE , ElementType.TYPE_PARAMETER
两个都删除的话,就会看到报错,这是因为 ElementType.TYPE_USE
能代替ElementType.TYPE_PARAMETER
。具体ElementType.TYPE_USE能代替几个ElementType枚举中的常量,感兴趣的话,自己可以动手测试一下。
static void getCustomAnnotation() throws NoSuchMethodException {
AnnotationTest<String> annotationTest = new AnnotationTest<>();
final Class<? extends AnnotationTest> annotationTestClass = annotationTest.getClass();
//获取类上的注解
final CustomAnnotation classAnnotation = annotationTestClass.getAnnotation(CustomAnnotation.class);
System.out.println("类上的注解"+Arrays.toString(classAnnotation.types()));
//获取泛型上的注解
final TypeVariable<? extends Class<? extends AnnotationTest>>[] typeParameters = annotationTestClass.getTypeParameters();
for (TypeVariable<? extends Class<? extends AnnotationTest>> typeParameter : typeParameters) {
final CustomAnnotation annotation = typeParameter.getAnnotation(CustomAnnotation.class);
System.out.println("泛型上的注解:"+annotation);
}
//获取方法上的注解
final Method[] declaredMethods = annotationTestClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
final Annotation[] declaredAnnotations = declaredMethod.getDeclaredAnnotations();
for (Annotation declaredAnnotation : declaredAnnotations) {
System.out.println("方法名="+declaredMethod+",注解="+declaredAnnotation);
}
}
}
结果:
注解是Java中很重要的一个知识点,用起来也简单。它是类、方法、属性等的一个标记,搭配反射使用能够出奇效。
参考资料:
https://www.geeksforgeeks.org/annotations-in-java/