基本概念
注解在我们日常开发中经常使用,例如@Override注解(用于方法重写)、@SuppressWarnings注解(用于解除警告),注解通常放在类、方法、属性的上面,即注解可以作用于类、方法和属性。
下面简单来看一下@Override注解和@SuppressWarnings注解的源码
@Override注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@SuppressWarnings注解:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
通过简单对比可以发现,这两个注解上面都有两个注解:@Target和@Retention;我们把这种作用于注解上面的注解成为元注解,这两个注解都是每个注解都需要有的。下面简单分析一下这两个元注解:
@Target注解:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
通过@Target注解的源码可以发现,这个注解里有一个ElementType[]数组类型的属性,即value属性的值是ElementType类型的一个或多个;
ElementType枚举类:
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
通过这个枚举中的实例名以及每个实例上的的注释我们可以知道他们的作用;通过上面的分析我们可以知道@Target注解这个注解是为了定义注解所作用的范围,例如@Override注解上的@Target注解中的值只有METHOD,即说明@Override注解只能作用于方法上;而@SuppressWarnings注解可以作用于类、方法和属性等等;
@Retention注解:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
通过@Retention注解的源码可以发现,这个注解里有一个RetentionPolicy类型属性,即value属性的值是一个ElementType类型的值;
RetentionPolicy枚举类:
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
这个枚举类有三个值,分别为SOURCE、CLASS和RUNTIME,这三个属性表明注解的作用时间,SOURCE表明是源码期间,CLASS表明是编译期间,RUNTIME表明是运行期间;通过@Override注解可以看到它的@Retention注解的值是SOURCE,所以我们在重写方法没有在方法上加@Override注解时,代码就会报错。
自定义一个注解
上面我们简单看了@Override注解和@SuppressWarnings注解的源码,下面我们尝试自定义一个简单的注解。
@Target({ElementType.TYPE, ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface CustomerAnnotation {
String value();
String[] desc() default "";
}
简单分析一下这个简单的代码:自定义注解@CustomerAnnotation中有两个属性,分别为value属性和desc属性(注意:注解中的属性后面是需要加()的,不要把它们当成方法),这个属性后面有个default,表明这个属性的默认值,即如果使用该注解时,如果不给desc属性赋值,则该属性的值为"";通过@Target注解中的值可以确定该自定义注解可以作用于类或属性上;通过@Retention注解中的值可以确定该注解在运行时起作用;注解中的属性的命名有一个特别的地方,如果属性名为value,那么在注解中就可以省略属性名。下面简单的使用这个自定义注解:
@CustomerAnnotation(value = "abc")
public class AnnotationDemo {
@CustomerAnnotation(value = "123",desc = {"haha","xixi"})
private String name;
}
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface CustomerAnnotation {
String value();
String[] desc() default "";
}
注意:如果注解中只有一个属性,并且属性的名字是value,则在使用注解时,可以省略 value = ;即 @注解(“abc”)