一篇文章了解Java注解(Annotation)
Java注解(Annotation)
什么是注解?
- 定义:注解(Annotation),也叫元数据。一种代码级别的说明。
它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。
它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
注解的作用?
- 用来解释说的
注释:用来解释说明的,给程序员看的
注解:用来解释说明的,给程序看的
1. 编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
2. 代码分析:通过代码里标识的注解对代码进行分析【使用反射】
3. 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】
注解的书写位置?
@注解名字public Tools {}------------------@注解名字public Tools {@注解名字public void show() {}}------------------class Tools {@注解名字private int age;}------------------class Tools {public void show(@注解名字 int i, @注解名字 int j) {}}
注解的分类?
预定义注解?
- 人家已经起好名字的注解,人家提供的,我们直接使用的
- @Override:作用是用来检查方法是否是重写方法
- @Deprecated:作用是用来标记方法是否已经过时
- @SuppressWarnings:作用是用来压制警告
- 注意:一般都会给参数设置为all,用来压制所有的警告
自定义注解?
-
自己写的注解,自己起的名字
-
注解的定义格式?
元注解修饰符 @interface 注解名字 {}例子:public @interface MyAnno { }
注解的本质?
- 注解的本质就是一个接口,只不过该接口默认继承了Annotation接口
public interface MyAnno1 extends java.lang.annotation.Annotation {}
注解的属性?
- 因为接口中有很多抽象方法,在接口中定义的方法就称为抽象方法,在注解中定义的抽象方法就称为属性
属性的定义?
public @interface MyAnno {数据类型 属性名();}举例子:public @interface MyAnno {String aaa();}注意:数据类型不是随便想写哪个就写哪个,而是固定的几个才可以
属性的数据类型可以为以下几种?
- 基本数据类型
- String
- 枚举
- 注解
- 以上几种数据类型对应的数组类型
public @interface MyAnno2 {int aaa();String bbb();MyEnum ccc();MyAnno1 ddd();String[] eee();}
属性的使用?
@MyAnno2(aaa=12)@MyAnno2(bbb="abc")@MyAnno2(ccc=MyEnum.M1)@MyAnno2(ddd=@MyAnno1)@MyAnno2(eee="aaa")@MyAnno2(eee= {"aaa"})@MyAnno2(eee= {"aaa", "bbb", "ccc"})class C {}
我们在使用注解的时候需要注意哪些问题?
-
如果一个注解中存在多个属性的时候,我们在使用需要给这些属性都要赋值,属性
与属性之间要用逗号隔开 -
我们可以注解中的属性设置默认值(default),一旦设置了默认值,我们在使用
属性的时候,就不需要给该属性赋值了,当然也可以赋值 -
注解中有一个非常特殊的属性名,叫做value,一旦我们起的属性名字叫做value,
我们在使用注解给该属性赋值的时候,其实是不需要写属性名的,前提条件是该
注解有且只有一个属性
元注解?
什么是元注解?
- 用来标注注解的注解就称为元注解
元注解有哪些呢?
-
*@Target:约束被该注解所标注的注解的书写范围
ElementType.TYPE:如果设置这个属性值,被标注的注解只能放在类的上面
ElementType.FIELD:如果设置这个属性值,被标注的注解只能放在属性的上面
ElementType.METHOD:如果设置这个属性值,被标注的注解只能放在方法的上面 -
*@Retention:设置被该注解所标注的注解的声明时长
RetentionPolicy.SOURCE:存活在源文件期间,编译之后就消失了
RetentionPolicy.CLASS:存活在源文件期间和字节码文件期间,运行之后就消失了
RetentionPolicy.RUNTIME:存活在源文件期间和字节码文件期间和运行期间 -
@Documented:被该注解所标注的注解能够存在于帮助文档中
-
@Inherited:被该注解所标注的注解能够被子类继承
注解的解析?
- 通过反射技术,来获取注解中的属性的值
注意:想要对注解进行解析,前提条件@Retention(RetentionPolicy.RUNTIME)
1.获取类上面的注解的属性值?
public class Demo01 {public static void main(String[] args) throws Exception {//使用反射技术获取类上面的注解的属性值:tom,18//获取字节码文件对象Class clazz = Class.forName("com.annotation.A");//获取类上面的注解对象//Annotation annotation = clazz.getAnnotation(MyAnno1.class);MyAnno1 myanno = (MyAnno1)clazz.getAnnotation(MyAnno1.class);System.out.println(myanno);//获取name和age的属性值String name = myanno.name();int age = myanno.age();System.out.println(name + "..." + age);}}@MyAnno1(name="tom", age=18)class A {}
2.获取方法上面的注解的属性值?
public class Demo02 {public static void main(String[] args) throws Exception {//获取字节码文件对象Class clazz = Class.forName("com.annotation.B");//获取show方法对象Method method = clazz.getMethod("show");//获取方法上的注解对象MyAnno1 myAnno1 = method.getAnnotation(MyAnno1.class);//获取name和age属性值String name = myAnno1.name();int age = myAnno1.age();System.out.println(name + "..." + age);}}class B {@MyAnno1(name="jerry",age=19)public void show() {}}
3.获取属性上面的注解的属性值?
public class Demo03 {public static void main(String[] args) throws Exception {//获取字节码文件对象Class clazz = Class.forName("com.annotation.C");//获取name属性对象Field field = clazz.getDeclaredField("name");//获取name属性上的注解对象MyAnno1 myAnno1 = field.getAnnotation(MyAnno1.class);//获取name和age属性值String name = myAnno1.name();int age = myAnno1.age();System.out.println(name + "..." + age);}}class C {@MyAnno1(name="rose",age=20)private String name;}