概念
简单使用
定义
//指定该注解的保留策略:运行时保留
@Retention(RetentionPolicy.RUNTIME)
//指定该注解的标注位置:类、字段、方法
@Target(value={ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
public @interface MyAnnotation{
//属性
String value();
int age() default 20;
}
标注
注解可以标注在类、方法、字段等元素上。
@MyAnnotation(value="我在类上",age=10)
public class Main{
@MyAnnotation("我在字段上")
private int filed;
@MyAnnotation("我在方法上")
public void method(){
}
}
获取
通过反射获取注解(Class、Method、Field)。
//获取类上所有注解
Annotation[] anns = Main.class.getAnnotations();
//获取类上指定注解
MyAnnotation ann = Main.class.getAnnotation(MyAnnotation.class);
//获取字段指定注解
ann = Main.class.getField("filed").getAnnotation(MyAnnotation.class);
//获取方法指定注解
ann = Main.class.getMethod("method").getAnnotation(MyAnnotation.class);
System.out.println(ann.value()+":"+ann.age());
本质
注解的本质是继承java.lang.annotation.Annotation
的一个接口。
public interface MyAnnotation extends Annotation{
//属性
}
Annotation
public interface Annotation {
//判断两个注解实例是否相同
boolean equals(Object obj);
//返回此注解的哈希码
int hashCode();
//返回此注解的字符串表示形式
String toString();
//返回此注解的注解类型
Class<? extends Annotation> annotationType();
}
属性
注解的属性就是注解接口类中的方法。
类型限定
注解属性的返回值类型只允许以下几种:
- 基本数据类型
- String
- 枚举
- 注解
- 以上类型的数组
默认值
定义属性时,可以使用default
关键字给属性默认初始化值。在使用注解时,对有默认值的属性可以不赋值。
省略value
如果只有一个属性需要赋值,并且属性的名称叫value
,那么使用时可以省略value
,直接定义值即可。
数组赋值
数组赋值时,值使用{}包裹,若数组中只有一个元素,则{}可以省略。
相关注解
元注解
@Documented
@Documented注解表明这个注解是由 javadoc记录的。
如果一个类型声明被注解了文档化,它的注解成为公共API的一部分。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
例如:@Documented
@Retention
@Retention作用是定义被它所注解的注解保留多久。
一共有三种策略,定义在RetentionPolicy枚举中。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
例如:@Retention(RetentionPolicy.RUNTIME)
RetentionPolicy
public enum RetentionPolicy {
/**
* 注解只在源代码级别保留,编译时被忽略
*/
SOURCE,
/**
* 注解将被编译器在类文件中记录
* 但在运行时不需要JVM保留。
*/
CLASS,
/**
* 注解将被编译器记录在类文件中
* 在运行时保留VM,因此可以反读。
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
@Target
@Target描述了注解的使用范围。
具体元素范围在ElementType枚举中。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
例如:
@Target(ElementType.ANNOTATION_TYPE)
@Target(value={ElementType.ANNOTATION_TYPE,ElementType.FIELD})
ElementType
public enum ElementType {
/** 类, 接口(注解), 或枚举声明 */
TYPE,
/** 字段声明(包括枚举常量) */
FIELD,
/** 方法声明(Method declaration) */
METHOD,
/** 参数声明 */
PARAMETER,
/** 构造函数声明 */
CONSTRUCTOR,
/** 局部变量声明 */
LOCAL_VARIABLE,
/** 注解类型声明 */
ANNOTATION_TYPE,
/** 包声明 */
PACKAGE,
/**
* 类型参数声明
* @since 1.8
*/
TYPE_PARAMETER,
/**
* 使用的类型
* @since 1.8
*/
TYPE_USE
}
@Inherited
描述注解是否被子类继承。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
JDK自带注解
@Override
监测被该注解标注的方法是否是继承自父类的。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
例如:@Override
@Deprecated
表示已过时
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
@Deprecated
@SuppressWarnings
压制警告,忽略警告
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
例如:@SuppressWarnings("unchecked")
获取注解
可以通过Java反射来获取注解(Class、Method、Field)。
//获取类上所有注解
Annotation[] anns = Main.class.getAnnotations();
//获取类上指定注解
MyAnnotation ann = Main.class.getAnnotation(MyAnnotation.class);
//获取字段指定注解
ann = Main.class.getField("filed").getAnnotation(MyAnnotation.class);
//获取方法指定注解
ann = Main.class.getMethod("method").getAnnotation(MyAnnotation.class);
System.out.println(ann.value()+":"+ann.age());
总结
- 大多数时候,我们会使用注解,而不是自己定义注解
- 注解给谁用?
- 编辑器(Idea等)
- JVM正常运行用。
Comments | NOTHING