注解,通常被理解为注释、标识,我觉得注解可以理解为修饰。
即被注解标注的类、变量、方法等,是为了达到某一个特定的效果。
Java中的元注解有4个,@Target,@Retention,@Documented和@Inherited。元注解可以理解为注解的注解,顾名思义,修饰注解的注解。
@Target
target定义注解出现的地方,换句话说,说明注解修饰的对象,这里的值均已枚举的方式出现。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
参考Target注解源码,返回的是一个枚举类型数组,里面定义了枚举可以返回的值类型
public enum ElementType {
/** 类,接口(包括注解类型)或enum声明 */
TYPE,
/** 域(属性信息)声明(包括 enum 实例) */
FIELD,
/** 方法(函数)声明 */
METHOD,
/** 常用参数声明 */
PARAMETER,
/** 构造方法声明 */
CONSTRUCTOR,
/** 局部变量声明 */
LOCAL_VARIABLE,
/** 注解声明 */
ANNOTATION_TYPE,
/** 包声明 */
PACKAGE,
/** 参数类型声明 */
TYPE_PARAMETER,
/** 类型的使用 */
TYPE_USE
}
以上是@Target可以使用的枚举值
@Retention
retention标注注解的保留范围,有源码、编译类和运行时三个范围
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
参考上面的注释,可以看到,Retention注解反馈一个保留策略结果,继续看RetentionPolicy源码
public enum RetentionPolicy {
/** 被编译器丢弃,注解仅留在源码中,即注解不会编译到class文件中 */
SOURCE,
/** 注解被编译器记录在class文件中,但是不会保留到运行期。这个是保留策略的默认行为 */
CLASS,
/** 注解被编译器记录在class文件中,并被Java虚拟机在运行期保留,可以被反射读到 */
RUNTIME
}
三个保留策略的保留范围 SOURCE < CLASS < RUNTIME
@Documented
documented注解修饰的元素可以被 javadoc 类的工具文档化。它代表着此注解会被javadoc工具提取成文档,在doc文档中的内容会因为此注解的信息内容不同而不同。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
@Inherited
inherited注解修饰的类,子类可以继承父类中的注解。即拥有此注解的元素其子类可以继承父类的注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
示例:
这里有三个类,工作注解WorkAnnotation.java,工作类Work.java 和测试主类 WorkTest.java
WorkAnnotation.java 注解定义类,定义三个属性:最大工作小时 maxWorkHour ,姓名最大长度maxNameLength 和 工作类型 workType。
package com.meta.annotation;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 定义工作注解
* @author Administrator
*/
@Retention(RetentionPolicy.RUNTIME) //JVM会保留这个注解。
@Target({FIELD, METHOD}) //这个元注解是说明这个注解的目标是用于方法的。
public @interface WorkAnnotation {
// int型注解属性,最大工作时间。
int maxWorkHour() default 8;
// int型注解属性, 用户姓名最大长度
int maxNameLength() default 10;
// String型注解属性,工作类型
String workType() default "";
}
工作主类 Work.java 工作主类中,用到两个@WorkAnnotation注解的属性,并附详细注释,加以说明
package com.meta.annotation;
import java.lang.reflect.Method;
/**
* 工作主类
* 注解的具体应用
* @author Administrator
*/
public class Work {
@WorkAnnotation(maxWorkHour = 7)
public void setMaxWorkHour(int maxHour)throws SecurityException, NoSuchMethodException{
// 获取当前method对象
Class<? extends Work> clazz = this.getClass();
Method method = clazz.getDeclaredMethod("setMaxWorkHour",int.class);
// 判断当前方法是否有使用@WorkAnnotation注解
if(method.isAnnotationPresent(WorkAnnotation.class)){
// 通过method方法对象来获取@WorkAnnotation注解,并获取注解值
WorkAnnotation wa = method.getAnnotation(WorkAnnotation.class);
int maxWorkHour = wa.maxWorkHour();
// 注解值具体用法判断
if(maxHour > maxWorkHour) {
throw new RuntimeException("最大的工作时间为"+ maxWorkHour + "小时。");
}
System.out.println("工作时间设置成功,为" + maxHour + "小时。");
}
}
@WorkAnnotation(maxNameLength = 10)
public void setUsername(String username) throws NoSuchMethodException, SecurityException {
Class<? extends Work> clazz = this.getClass();
Method method = clazz.getDeclaredMethod("setUsername", String.class);
if(method.isAnnotationPresent(WorkAnnotation.class)){
WorkAnnotation wa = method.getAnnotation(WorkAnnotation.class);
int maxNameLength = wa.maxNameLength();
if (username == null || username == "") {
System.out.println("username设置失败,username 值为空");
} else if (username.length() <= maxNameLength) {
System.out.println("username设置成功,username = " + username);
} else {
throw new RuntimeException("username最大程度为" + maxNameLength + ",实际长度为" + username.length());
}
}
}
}
WorkTest.java 测试类
package com.meta.annotation;
public class WorkTest {
public static void main(String[] args) throws SecurityException, NoSuchMethodException {
Work work = new Work();
work.setMaxWorkHour(9);
work.setUsername("zhangsan");
}
}
Work.java中,setMaxWorkHour方法上面,注解@WorkAnnotation(maxWorkHour = 7) 属性值是7,这个7会覆盖掉WorkAnnotation.java 中默认的8,运行WorkTest.java
会抛出异常 ,是因为设置的值和注解的值冲突了
修改设置的值为6,成功运行成功
maxNameLength属性的测试方法和maxWorkHour类似,不再重复描述了。
上面是最近几天看注解的一点整理,如有不当支持,欢迎留言批评斧正。谢谢。