Java注解(Annotation)
1. 注解(Annotation)介绍
注解(Annotation)是从Jdk1.5引入的新技术
1.1 注解(Annotation)的作用
- 不是程序本身,可以对程序作出解释
- 可以被其他程序(比如:编译器读取)。
**注解信息的处理流程是注解与注释的最大区别。**如果没有注解信息处理流程,则注解毫无意义。
1.2 注解(Annotation)的格式
- 以“@注释名”在代码中存在,如:
@Override,@Autowired
1.3 注解(Annotation)使用的地方
可以添加在package, class, method, field等上面,相当于给它们添加了额外的辅助信息,我们可以通过反射机制变成实现对这些元数据的访问。
2. 内置注解
2.1 @Override
定义在java.lang.Override中,此注释只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明。
2.2 @Deprecated
定义在java.lang.Deprecated中,此注释可用于修辞方法、属性、类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。
2.3 @SuppressWarnings
定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息。如:
@SuppressWarnings(“unchecked”)
@SuppressWarnings(value={“unchecked”,“deprecation”})
@SuppressWarnings(“all”)
3. 自定义注解@interface
-
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
-
格式及要点:
1)public @interface 注解名 {定义体}
2)其中的每一个方法实际上是声明了一个配置参数。
3)方法的名称就是参数的名称。
4)返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。
5)可以通过default来声明参数的默认值。
6)如果只有一个参数成员,一般参数名为value。
注解元素必须要有值。我们定义注解元素时,经常使用空字符串、0作为默认值。也经常使用负数(比如:-1)表示不存在的含义
例子:
public @interface Annotation01 {
String name() default "";
int age() default 0;
int id() default -1;
String[] schools() default {"清华大学", "北京大学"};
}
public @interface Annotation02 {
String value();
}
4. 元注解
- 元注解的作用就是负责注解其他注解。 Java定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。
- 这些类型和它们所支持的类在java.lang.annotation包中可以找到
- @Target
- @Retention
- @Documented
- @Inherit
4.1 @Target
用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
修饰范围 | 取值ElementType |
---|---|
package 包 | PACKAGE |
类、接口、枚举、Annotation类型 | TYPE |
类型成员(方法、构造方法、成员变量、枚举) | CONSTRUCTOR:用于描述构造器 Field:用于描述域 METHOD:用于描述方法 |
方法参数和本地变量 | LOCAL_VARIABLE:用于描述局部变量 PARAMETER:用于描述参数 |
- @Target(value=ElementType.TYPE)
- @Target(value={ElementType.METHOD,ElementType.TYPE})
4.2 @Retention
表示需要在什么级别保存该注释信息,用于描述注解的生命周期。
RetentionPolicy | 作用 |
---|---|
SOURCE | 在源文件中有效 |
CLASS | 在class文件中有效 |
RUNTIME | 在运行时有效,RUNTIME可以被反射机制读取 |
4.3 @Documented
声明注解能够被javadoc等识别。
4.4 @Inherit
声明子类可以继承此注解,如果一个类A使用此注解,则类A的子类也继承此注解。
4.5 例子
定义一个自定义注解(使用元注解,每个元注解都是可选,非必选)。
@Target(value={ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Annotation01 {
String name() default "";
int age() default 0;
int id() default -1;
String[] schools() default {"清华大学", "北京大学"};
}
@Target(value= {ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Annotation02 {
String value();
}
@Annotation01
public class demo2 {
@Annotation01(name="zhangsan", id=1001, age=28, schools={"西安交通大学","西北工业大学"})
public void test1() {
}
@Annotation02("aaa")
public void test2() {
}
}
5. 通过反射解析注解
5.1 定义一个Table注解
@Target(value= {ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}
5.2 定义一个Field注解
@Target(value= {ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Field {
String columnName();
String type();
int length();
}
5.3 将注解添加到实体类User中
@Table("tb_user")
public class User {
@Field(columnName="id", type="int", length=10)
private int id;
@Field(columnName="user_name", type="varchar", length=20)
private String name;
@Field(columnName="age", type="int", length=3)
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
5.4 测试通过反射获得注解信息
public class TestUserAnnotation {
public static void main(String[] args) {
try {
Class clazz = Class.forName("com.stormkai.annotation.User");
//获得类的所有有效注解
Annotation[] annotations = clazz.getAnnotations();
for(Annotation a: annotations) {
System.out.println("a="+a);
}
//获得类的指定的注解
Table t = (Table) clazz.getAnnotation(Table.class);
System.out.println("t.value()="+t.value());
//获得类的属性name的注解
java.lang.reflect.Field f = clazz.getDeclaredField("name");
Field field = f.getAnnotation(Field.class);
System.out.println(field.columnName()+"---"+field.type()+"---"+field.length());
//获取类的所有属性的注解
Field field1;
java.lang.reflect.Field[] ff = clazz.getDeclaredFields();
for(int i=0; i<ff.length; i++) {
ff[i].setAccessible(true);
field1 = clazz.getDeclaredField(ff[i].getName()).getAnnotation(Field.class);
System.out.println(field1.columnName()+"---"+field1.type()+"---"+field1.length());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试结果:
a=@com.stormkai.annotation.Table(value=tb_user)
t.value()=tb_user
user_name---varchar---20
id---int---10
user_name---varchar---20
age---int---3
5.5通过解析注解拼接DDL语句
public class TestUserAnnotation {
public static void main(String[] args) {
try {
Class clazz = Class.forName("com.stormkai.annotation.User");
//根据获得的表名,字段的信息,拼出DDL语句
Annotation[] annotations = clazz.getAnnotations();
Table t = (Table) clazz.getAnnotation(Table.class);
StringBuilder sb = new StringBuilder();
sb.append("create table "+t.value()+"( ");
Field field;
java.lang.reflect.Field[] ff = clazz.getDeclaredFields();
for(int i=0; i<ff.length; i++) {
ff[i].setAccessible(true);
field = clazz.getDeclaredField(ff[i].getName()).getAnnotation(Field.class);
System.out.println(field.columnName()+"---"+field.type()+"---"+field.length());
sb.append(field.columnName()+" "+field.type()+"("+field.length()+"), ");
}
String str = sb.substring(0, sb.lastIndexOf(","));
str+=" );";
System.out.println(str);
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出结果:
id---int---10
user_name---varchar---20
age---int---3
create table tb_user( id int(10), user_name varchar(20), age int(3) );