参考:《java编程思想》
一。注解分为3类:
1.标准注解(3个):
- @Override:标识该方法继承自超类。
- @Deprecated:表示该类或者方法已经不推荐使用。
- @SuppressWarnings:用于忽略的编译器警告信息。
2.元注解(4个):
@Documented:将此注解包含在javadoc中。
@Inherited:允许子类继承父类中的注解。
-
@Target:描述注解的使用范围。
ElementType取值:1.CONSTRUCTOR:用于描述构造器 2.FIELD:用于描述域 3.LOCAL_VARIABLE:用于描述局部变量 4.METHOD:用于描述方法 5.PACKAGE:用于描述包 6.PARAMETER:用于描述参数 7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
-
Retention:表示需要在什么级别保存该注解信息。
RetentionPolicy参数取值:1.SOURCE:注解将被编译器丢弃。 2.CLASS:注解在class文件中可用,但会被VM丢弃。 3.RUNTIME:VM将在运行期保留注解,因此可以通过反射机制来读取注解的信息。
3.自定义注解:
元注解专职负责注解其他的注解,因此举例以下自定义注解:
TestAnnotation.java注解类
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
int id(); //这个就是注解元素
String desc() default "no description";
}
值得注意:
1、注解元素的类型为:
- 所有基本类型(int,float,boolean等)。
- String
- Class
- enum
- Annotation
- 以上类型的数组
2、注解元素默认值的限制:
注解元素的默认值不能为null,需要定义表示空时,可以自己定义特殊的值如:int id() default -1;String desc() default "";
二.自定义注解实战:
想象数据库的各种元素:数据库名称,约束关系,字段属性等。
看以下关系:
先定义DBTable注解,用于定义数据库的名称:
package db;
import java.lang.annotation.*;
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {
String value() default "";//默认为空,不能写null
}
再看Constants,用于定义约束关系:
package db;
import java.lang.annotation.*;
@Documented //生成javadoc
@Inherited //让子类继承父类的注解
@Target(ElementType.FIELD) //修饰字段
@Retention(RetentionPolicy.RUNTIME) //运行时保留注解
public @interface Constants {
boolean primaryKey() default false;
boolean allowNull() default true;
}
再看ColumnString,定义字段属性:
package db;
import java.lang.annotation.*;
@Documented
@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnString {
String value() default "";
Constants constants() default @Constants;
}
再看ColumnInteger,定义字段属性:
package db;
import java.lang.annotation.*;
@Documented
@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnInteger {
int value() default -1;
Constants constants() default @Constants;
}
所有注解都准备好了,现在定义Person类:
package db;
@DBTable("Person")
public class Person {
@ColumnInteger(value = 1, constants = @Constants(primaryKey = true, allowNull = false))
private int id;
@ColumnInteger(value = 24)
private int age;
@ColumnString(value = "dxj")
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
现在要编写注解解析器:
public class AnonotationTest {
public static void main(String[] args) {
getPersonAnnotation(Person.class);
}
public static void getPersonAnnotation(Class<?> cl) {
//获取类的注解
Annotation[] declaredAnnotations = cl.getDeclaredAnnotations();
for (Annotation annotation : declaredAnnotations) {
if (annotation instanceof DBTable) {
System.out.println("数据库名称:" + ((DBTable) annotation).value());
}
}
//获取类的字段
Field[] declaredFields = cl.getDeclaredFields();
for (Field f : declaredFields) {
//获取字段的注解
Annotation[] fDeclaredAnnotations = f.getDeclaredAnnotations();
for (Annotation annotation : fDeclaredAnnotations) {
if (annotation instanceof ColumnString) {
System.out.println("字段名:" + f.getName() + ",字段长度:" + ((ColumnString) annotation).value() +
",是否主键:" + ((ColumnString) annotation).constants().primaryKey() +
",是否允许为空:" + ((ColumnString) annotation).constants().allowNull());
}
if (annotation instanceof ColumnInteger) {
System.out.println("字段名:" + f.getName() + ",字段长度:" + ((ColumnInteger) annotation).value() +
",是否主键:" + ((ColumnInteger) annotation).constants().primaryKey() +
",是否允许为空:" + ((ColumnInteger) annotation).constants().allowNull());
}
}
}
}
}
最后输出的结果为:
注解解析器通过反射获取注解上的值。