注解可以简单理解为代码的特殊标记,可以在编译、加载或运行时被加载。
1. 元注解
@Target 表示该注解使用范围
可选的ElementType参数有:
CONSTRUCTOR:用于构造器声明
FIELD:域声明(包括enum实例)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注解类型)或enum声明
@Retention 表示注解保存级别
可选RetentionPolicy参数有:
SOURCE:注解将被编译器丢弃
CLASS:注解在class文件中可用,但会被VM丢弃
RUNTIME:VM将在运行期间保留注解,因此可以通过反射机制读取注解的信息
@Document 将注解包含到javaDoc中
@Inherited 允许子类继承父类注解
2. 自定义注解及使用
2.1. 创建注解类
public @interface SubscribeAnnotation {
}
2.2. 添加元注解
@Target(ElementType.METHOD) // 注解可用在方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时保留,常用于与AOP组合,实现面向切面编程
// @Document
@Inherited // 子类重构的方法将继承该注解
public @interface SubscribeAnnotation {
}
2.3. 为注解增加“属性”
import common.Publish;
import java.lang.annotation.*;
/**
* 自定义注释
* @author pinzhong
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SubscribeAnnotation {
// 1. 未设置默认值的属性需在使用时明确指定其值
// 2. 当只有一个没有默认值的属性且命名称为vale时,为其赋值时可省略参数名
// 3. 此处结合使用时可理解为啥标题称之为【“属性”】
String value();
Class<? extends Publish> publish() default Publish.class;
}
2.4. 使用注解
创建一个类,根据自定义注释@Target的使用范围限制(示例中我们指定为方法)进行使用:
public class TestAnnotation {
@SubscribeAnnotation(value= "testPub", publish = Publish.class) // 结合2.3中value()处3的注释
public void publish(){}
@SubscribeAnnotation("name") // 结合2.3中vale()的注释
public void publish(String s){}
public static void main(String[] args) {
// 使用反射获取注解
Method[] methods = TestAnnotation.class.getMethods();
for (Method method : methods) {
Annotation[] annotations = method.getAnnotations();
if (annotations != null && annotations.length > 0)
for (Annotation anno : annotations) {
if (anno.annotationType().equals(SubscribeAnnotation.class))
System.out.println("TestAnnotation." + method.getName() + " has SubscribeAnnotation annotation!");
}
}
}
}
输出结果:
TestAnnotation.publish has SubscribeAnnotation annotation!
TestAnnotation.publish has SubscribeAnnotation annotation!
文末语:
自定注解其实很简单,简单来说定义一个@interface类,在其类上添加元注解标明该注解的使用范围、保存级别、是否保存到JavaDoc中、是否允许子类继承,最后添加“属性”即可;难处在使用上,后续会补充上该处文章。