赞
踩
Annotation是从JDK5.0开始引入的新技术
Annotation的作用:
Annotation的格式:
Annotation在哪里使用:
定义在java.lang包中,此注解只适用于修饰方法,表示该方法打算重写父类中的同名方法,并且具有检查作用
public class Person {
public void test () {
}
}
class Student extends Person {
@Override
public void test () {
}
}
定义在java.lang包中,此注释可以修饰方法、属性、类,注释@Deprecated的程序元素是程序员不鼓励使用的程序元素,通常是因为它是危险的,或者因为它已经过时了,然后存在更好的替代方法,但是你使用也没有任何影响
表示test()方法已经失效。
定义在java.lang包中,用来抑制编译时产生的黄色警告信息,虽然这些警告信息不会影响编译结果,但是看着不舒服,然后该注释和前两个注释有所不同,你需要添加一个参数才能正确使用。
具体参数信息如下所示:
注意:public @interface SuppressWarnings {String[] value();}
,其中value是参数名,而String[]是参数是类型,当注解只使用value这一个参数的时候,value可以省略,例如上面的@SuppressWarnings(“all”)和@SuppressWarnings(“unchecked”)就是省略了前面的value,但是仅限参数名是value,并且注解中只使用value这一个参数的情况才可以 省略value,下面也会提到。
什么是元注解?元注解就是对其他普通注解进行说明解释的注解。
java中定义了4个元注解,自动继承了java.lang.annotation.Annotation
@Target限定了一个注解的使用范围,作用域,默认可以在任何地方使用,也可以指定使用的范围。
以**@Override注解为例,我们打开@Override**注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
点击进入**@Target(ElementType.METHOD)**
@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();
}
我们看到注解需要传入一个key为value的数组ElementType[] value()。点开ElementType[]
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, // 可用于类、接口或enum声明 /** 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 // 类型的使用 }
ElementType枚举定义了各种注解使用的范围。
测试:
缺失value
不传参数直接报错,应为注解内部定义了ElementType[] value()
将自定义注解的作用域设置到方法上,只能在方法上使用,在类上使用报错。
传入两个参数作用域,限制注解在方法和类上使用,我们发现注解可以在类上面正常使用了。
@Retention注解声明了注解使用的周期,用于定义注解的存活阶段,可以存活在源码级别、编译级别(字节码级别)、运行时级别。
以**@Override注解为例,我们打开@Override**注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
进入**@Retention(RetentionPolicy.SOURCE)**
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
注解需要传入一个key为value的RetentionPolicy,进入RetentionPolicy
public enum RetentionPolicy { /** * Annotations are to be discarded by the compiler. */ SOURCE, // 源码级别,注解只存在源码中,一般用于和编译器交互,用于检测代码。如@Override, @SuppressWarings。注解将被编译器丢弃 /** * 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, // 字节码级别,注解存在于源码和字节码文件中,主要用于编译时生成额外的文件,如XML,Java文件等, // 但运行时无法获得。 如mybatis生成实体和映射文件,这个级别需要添加JVM加载时候的代理(javaagent) // 使用代理来动态修改字节码文件。 // 注解在class文件中可用,但会被VM丢弃 /** * 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 // 运行时级别,注解存在于源码、字节码、java虚拟机中,主要用于运行时,可以使用反射获取相关的信息。 // VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息 }
RetentionPolicy枚举定义了三个时间周期级别,大小是源码级别 < 字节码级别 < 运行时级别
。
将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。相当与@see,@param 等。
注解里面什么都没有,只是简单的标注
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
允许子类继承父类中的注解。也只是一个简单的标注。
以上四个元注解重点掌握@Target、@Retention
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation
接口。
@interface 用来声明一个注解,格式是:修饰符 @interface 注解名{定义内容}
我们来定义一个注解:
@MyAnnotation2(age = 18, name = "张三") public class Demo02 { } /** * @author HCAN */ @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation2 { // 注解的参数:参数类型 + 参数名称();这里的括号不是表示方法,而是定义了注解一个参数 String name() default ""; int age(); int id() default -1; String[] schools() default {"清华大学", "北京大学"}; }
说明:
1、自定义注解内部定义的name()这个是表示的定义的注解参数,不是方法。
2、如果在注解的参数定义的时候设置了default默认值,在使用参数的时候可以不传,如果没有定义就必须传参数,否则会提示报错。
3、注解的参数传入顺序和定义参数的顺序无关。比如name()在age()前面,但是我们使用注解的时候是可以把age放在name前面的。
扩展:
我们发现前面我们在查看@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();
}
我们明明将注解的参数名定义成了value(),为什么我们使用的使用的方式是@Target(ElementType.TYPE),没有使用@Target(value = ElementType.TYPE)
这是应为当我们注解参数只有一个的时候,我们可以把参数的名称定义为value(只能是value)
。这样我们在使用注解的时候可以不写value,直接传入参数即可
本文为狂神说学习笔记
学习地址:https://www.bilibili.com/video/BV1p4411P7V3
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。