1. 自定义注解(Annotation)
Annotation是从JDK 1.5开始,引入的新技术。
注解使用格式:
- @注解名
- 后边还可以跟上括号,以添加一些参数值
例如:
public class TestAnnotation {
// 使用@Override注解,标识此方法重写了父类的方法
@Override
public String toString() {
// ...
}
}
在哪里使用?
- 可以附加在package、class、method、field等上面,相当于给它们添加了额外的辅助信息
- 可以通过反射机制,编程实现对这些元数据(注解)的访问
内置注解:
Java中内置了3个注解(如前面的@Override
就是一个内置注解),它们的作用如下所示:
@Override
:表示一个方法重写了其父类的方法@Deprecated
:表示其修饰的内容不被推荐使用@SuppressWarnings(...)
:抑制编译时的警告信息,需要在括号中填入参数
元注解(meta-annotation,负责注解其它注解,自定义注解时使用):
元注解的作用是解释其它自定义的注解,也就是说,我们在自定义实现注解时,可以通过元注解对自定义注解的一些属性(如注解作用在哪、注解的生命周期等)进行限定。
JDK 1.5 定义了4个标准的元注解类型:
@Target
:描述注解的使用范围(用在什么地方,如类上、方法上 …)@Retention
:用于表述注解的生命周期(在什么地方有效,通常为RUNTIME)- SOURCE:注解在源文件中有效,将被编译器丢弃
- CLASS:注解在class文件中有效,将被JVM丢弃
- RUNTIME:注解在运行时有效,可以通过反射读取器信息
@Documented
:用于标记在生成javadoc时是否将注解包含进去@Inherited
:如果在注解上标记了@Inherited
,则说明子类可以继承父类中的该注解
自定义注解:
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口。
-
格式:public @interface 注解名 { 内容 }
-
其中的每一个方法实际上是在声明一个配置参数
-
格式:参数类型 参数名();
-
方法名称就是参数的名称
-
返回值类型就是参数的类型(只能是基本类型、Class、String、emun)
-
-
可以通过default来声明参数的默认值
-
如果只有一个参数成员,一般参数名为value(这样的话在使用时可以直接传入参数,无需特别指明
value = "..."
) -
注解元素必须要有值,在定义注解元素时,常使用空字符串、0作为默认值
示例:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface TestAnnotation {
String value();
int[] array();
}
2. 利用Reflection操作注解
自定义注解:
为了方便举例,这里模拟自定义了两个数据库表的注解,分别用于标识表和表中的列的信息。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DatabaseClass {
String value(); // 表名
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DatabaseField {
String columnName(); // 列名
String type(); // 类型
int length(); // 长度
}
在User类上增加注解:
有了前面自定义的两个注解,就可以对数据库表的对应类进行相应的标识。
@DatabaseClass("database_user")
public class User {
@DatabaseField(columnName = "id", type = "int", length = 11)
private int id;
@DatabaseField(columnName = "user_name", type = "String", length = 30)
private String userName;
@DatabaseField(columnName = "password", type = "String", length = 30)
private String password;
// ...
}
利用Reflection获取注解信息:
在用注解标识了相应的类之后,我们该如何获取这些“标识信息”呢?答案当然是:通过反射(Reflection)
public class ReflectionAnnotation {
public static void main(String[] args) throws NoSuchFieldException {
User user = new User();
Class userClass = user.getClass();
// 获取类上所有的注解
System.out.println("获取类上所有的注解:");
Annotation[] annotations = userClass.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
// 获得类上指定注解的值
System.out.println("获得类上指定注解的值:");
DatabaseClass databaseClass = (DatabaseClass) userClass.getAnnotation(DatabaseClass.class);
String databaseClassValue = databaseClass.value();
System.out.println(databaseClassValue);
// 获得字段上指定注解的值
System.out.println("获得字段上指定注解的值:");
Field id = userClass.getDeclaredField("userName");
DatabaseField databaseFieldValues = id.getAnnotation(DatabaseField.class);
System.out.println(databaseFieldValues.columnName());
System.out.println(databaseFieldValues.type());
System.out.println(databaseFieldValues.length());
}
}
运行结果: