元注解:是用来修饰其他注解的注解
类比:元数据:对现有数据修饰的数据
String name=“123”,String,name,“123”中最重要的是“123”,String和name可以看做是对“123”的修饰。如果把“123”看做数据,可以把String,name看做为元数据
@Override是用来修饰方法的,点击进入Override
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
就是元注解
JDK5.0提供了4个标准的meta-annotation类型,分别是:
- Retention :用于指定被修饰 Annotation 的生命周期:SOURCE\CLASS(默认)\RUNTIME
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "hello";
}
@MyAnnotation()
class Person{
private String name;
private int age;
只有声明为RUNTIME生命周期的注解,才能通过反射获取,注意是在使用的时候获取,比如Person类的上面用了MyAnnotation,就可以获取Person类上面所声明的这个注解
- Target :用于指定被修饰的 Annotation 能修饰哪些结构。
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
说明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();
}
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就是哪里都能用
@Retention(RetentionPolicy.RUNTIME)
@Target({ FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
public @interface MyAnnotation {
String value() default "hello";
}
因为没有TYPE,所以下面的代码报错,因为去修饰类了
@MyAnnotation()//报错
class Person{
private String name;
private int age;
public Person() {
自定义注解一般都要用到@Target和@Retention
下面这两个元注解使用频率较低
- Documented :表示所修饰的注解在被javadoc解析时保留下来。如果不用这个修饰是不会被保留的
比如
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
所以在API文档中有@Deprecated,API就是Javadoc解析出来的
- Inherited:被它修饰的 Annotation 将具有继承性。如果某个类使用了被 @Inherited 修饰的 Annotation, 则其子类将自动具有该注解。
可以通过反射获取注解信息
比如如果MyAnnotation用@Inherited进行修饰,虽然Student类的声明上方没有写,但实际上是有的,可以通过反射进行获取
public class test {
@Test
public void test1(){
Class clazz = Student.class;
Annotation[] annotations = clazz.getAnnotations();//获取类上面的注解,因为可能不止一个,所以返回的是数组
for(int i=0;i<annotations.length;i++){
System.out.println(annotations[i]);//@MyAnnotation(value=hello),这是父类的,如果把MyAnnotation中的@Inherited干掉了,就不会输出了
}
}
}
@MyAnnotation()
class Person{
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void walk(){
System.out.println("人走路");
}
public void eat(){
System.out.println("人吃饭");
}
}
interface Info{
void show();
}
class Student extends Person implements Info{
//Override就是注解,是在编译的过程中校验这个方法是不是重写父类,或者是实现接口中的方法也是Override
//只有方法上面才能用 @Override
@Override
public void walk() {//快速写法,walk+enter
System.out.println("学生走路");
}
@SuppressWarnings({"unused","rawtypes"})//点开它的结构,有点像类,可以往里面写多个值是因为里面有一个数组结构String[] value();
ArrayList list=new ArrayList();//注解是可以写多个值的,这些值就看做这个结构的成员变量
//接口,类可以有成员变量,只不过接口的是常量,不是变量
@Override
public void show() {//如果把show改成show1就会报错,因为加了Override注解,在编译的时候就回去校验,要求方法一定是重写父类或者是实现接口的方法
}
}
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
public @interface MyAnnotation {
String value() default "hello";
}