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;
}