1. 简介
在Java中,注解(Annotation)是一种元数据形式,它为代码添加了额外的信息,这些信息可以被编译器、工具、框架或运行时环境使用。注解提供了一种声明性的方式来向程序中添加元数据,而不需要修改程序的实际逻辑。
2. Java中常见的注解
2.1 内建注解(Built-in Annotations)
@Override
: 用于标识一个方法覆盖了父类中的方法。@Deprecated
: 用于标识已过时的方法或类,表示不再推荐使用。@SuppressWarnings
: 抑制编译器产生警告信息。
2.2 元注解(Meta-Annotations)
-
@Target
: 指定注解的应用范围,可以是类、方法、字段等。
该注解的ElementType
枚举值:ElementType.ANNOTATION_TYPE://表示该注解可以应用在其他注解上。ElementType.CONSTRUCTOR://表示该注解可以应用在构造方法上。ElementType.FIELD://表示该注解可以应用在字段(属性)上。ElementType.LOCAL_VARIABLE://表示该注解可以应用在局部变量上。ElementType.METHOD://表示该注解可以应用在方法上。ElementType.PACKAGE://表示该注解可以应用在包上。ElementType.PARAMETER://表示该注解可以应用在参数上。ElementType.TYPE://表示该注解可以应用在类、接口(包括注解类型)、枚举上。
-
@Retention
: 指定注解的保留策略,可以是源代码、编译时期或运行时期。-
RetentionPolicy.SOURCE
表示注解仅存在于源代码中,在编译时会被丢弃,不会保留在编译生成的字节码文件中。这意味着这种类型的注解在运行时是不可见的。 -
RetentionPolicy.CLASS
表示注解存在于编译生成的字节码文件中,但在运行时不可见。这是默认的保留策略,如果在 @Retention 中不显式指定,默认是 RetentionPolicy.CLASS。 -
RetentionPolicy.RUNTIME
表示注解在运行时是可见的,可以通过反射等机制获取注解信息。这种保留策略允许在运行时通过反射来处理注解。
-
-
@Documented
: 表示注解将包含在JavaDoc中。 -
@Inherited
: 表示注解可以被子类继承。
2.3 自定义注解
定义示例:
// 定义一个自定义注解
public @interface MyAnnotation {String value() default ""; // 注解元素,默认值为空字符串int count() default 0; //定义了一个名称为 count, 类型为int, 默认值为0的 注解元素
}
使用示例:
@MyAnnotation(value = "Hello", count = 5)
public class MyClass {// 类的内容
}
3. 获取注解信息
仅在 @Retention(RetentionPolicy.RUNTIME) 时使用
3.1 获取类注解信息
import java.lang.annotation.*;// 定义自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {String value() default "";int count() default 0;
}// 使用自定义注解
@MyAnnotation(value = "Hello", count = 5)
public class MyClass {public static void main(String[] args) {// 获取类上的注解MyAnnotation annotation = MyClass.class.getAnnotation(MyAnnotation.class);// 判断注解是否存在if (annotation != null) {// 访问注解中的元素值String value = annotation.value();int count = annotation.count();// 打印注解中的信息System.out.println("Value: " + value);System.out.println("Count: " + count);} else {System.out.println("MyAnnotation is not present on MyClass.");}}
}
3.2 获取方法的注释信息
定义注解
import java.lang.annotation.*;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyMethodAnnotation {String value() default "";int count() default 0;
}
使用注解
public class MyClass {@MyMethodAnnotation(value = "Hello Method", count = 10)public void myMethod() {// 方法的内容}
}
获取注解信息
import java.lang.reflect.Method;public class AnnotationExample {public static void main(String[] args) {// 获取类的Class对象Class<MyClass> myClassClass = MyClass.class;try {// 获取方法的Method对象Method method = myClassClass.getMethod("myMethod");// 获取方法上的注解MyMethodAnnotation methodAnnotation = method.getAnnotation(MyMethodAnnotation.class);// 判断注解是否存在if (methodAnnotation != null) {// 访问注解中的元素值String value = methodAnnotation.value();int count = methodAnnotation.count();// 打印注解中的信息System.out.println("Value: " + value);System.out.println("Count: " + count);} else {System.out.println("MyMethodAnnotation is not present on myMethod.");}} catch (NoSuchMethodException e) {e.printStackTrace();}}
}
3.3 获取属性的注解信息
定义注解
import java.lang.annotation.*;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyFieldAnnotation {String value() default "";int count() default 0;
}
使用注解
public class MyClass {@MyFieldAnnotation(value = "Hello Field", count = 20)private String myField;// 其他类内容...
}
获取注解信息
import java.lang.reflect.Field;public class AnnotationExample {public static void main(String[] args) {// 获取类的Class对象Class<MyClass> myClassClass = MyClass.class;try {// 获取字段的Field对象Field field = myClassClass.getDeclaredField("myField");// 获取字段上的注解MyFieldAnnotation fieldAnnotation = field.getAnnotation(MyFieldAnnotation.class);// 判断注解是否存在if (fieldAnnotation != null) {// 访问注解中的元素值String value = fieldAnnotation.value();int count = fieldAnnotation.count();// 打印注解中的信息System.out.println("Value: " + value);System.out.println("Count: " + count);} else {System.out.println("MyFieldAnnotation is not present on myField.");}} catch (NoSuchFieldException e) {e.printStackTrace();}}
}
getDeclaredField
方法的参数是字段的名称。如果字段是私有的,还需要通过field.setAccessible(true)
开启对私有字段的访问权限