元注解
- 元注解的作用:负责注解其他的注解,Java定义了4个标准的meta-annotation类型,他们用来提供对其他annotation类型做说明
- 这些元注解和他们所支持的类型在java.lang.annotation包中可以找到(@Target,@Retention,@Document,@Inherited)
1)@Target :用于描述注解的使用范围(即注解可以用在什么地方)
2)@Retention :表示需要在什么级别保存该注解信息,用于描述注解的生命周期
(SOURCE < CLASS < RUNTIME)
3)@Document :说明该注解将被包含在JavaDoc中
4)@Inherited : 说明子类可以继承父类中的该注解
自定义注解
- 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口
- 分析
1)@interface用来声明一个注解,格式:public @interface 注解名{定义内容}
2)其中每一个方法实际上就是声明了一个配置参数
3)方法的名称就是参数的名称
4)返回值类型就是参数的类型(返回值类型只能时基本类型,Class,String,eunm)
5)可以通过default来声明参数的默认值,调用时可以不给该参数赋值
6)如果只有一个参数成员,一般参数名为value,只有一个value时,使用注解时可省略参数名
7)注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值
8)定义注解的参数后面必须要有括号跟着,使其看起来像一个方法一样
下面还是来实际操作一下吧
@Target({ElementType.TYPE,ElementType.METHOD})//表示该注解可以放在类和方法上
@Retention(RetentionPolicy.RUNTIME)//表示该注解在运行时仍然有效
public @interface MyAnnotation {
int value() default 0;//表示该注解有一个参数叫value,并且默认值为0
String name();//表示该注解有一个参数叫name
}
@Target注解的value是个枚举
value是个枚举的数组,枚举如下,赋值哪个就代表可以将被标记的注解使用到何处
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
@Retention注解的value也是个枚举
只不过他的value不是数组,只能赋值一个
public enum RetentionPolicy {
SOURCE,//表示在源码阶段有效
CLASS,//表示在字节码时仍然有效
RUNTIME//表示在运行时仍然有效
}
如何通过反射来配合注解【核心】
下面就来创建一个模拟ORM框架的的注解示例
首先我们创建两个注解,分别为TableName和FieldInfo,然后设定其的作用域和参数值,最后将注解使用到pojo上
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableName{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldInfo{
String colName();
String type();
int length();
}
@TableName("db_student")
class Student{
@FieldInfo(colName = "stu_name",type = "varchar",length = 20)
private String name;
@FieldInfo(colName = "stu_id",type = "int",length = 10)
private int id;
@FieldInfo(colName = "stu_age",type = "int",length = 10)
private int age;
Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = 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 class AnnoTest {
public static void main(String[] args) throws NoSuchFieldException, ClassNotFoundException {
Class c1 = Class.forName("com.jxw.pojo.Student");
//获取类的注解要强转
TableName tableName = (TableName) c1.getAnnotation(TableName.class);
System.out.println(tableName.value());//直接调用注解写的类似方法的参数
Field field = c1.getDeclaredField("name");
//属性的注解却不需要强转
FieldInfo fieldInfo = field.getAnnotation(FieldInfo.class);
System.out.println(fieldInfo.colName());
System.out.println(fieldInfo.length());
System.out.println(fieldInfo.type());
}
}
运行结果: