自定义注解
注解(Annotation):是用于类(方法、属性…)定义上方,进而对该类(方法,属性…)进行描述,限制等。
说明:在自定义注解时,单单只是定义一个注解是没有任何意义的,必须配合反射,拦截器或过滤器等一起使用才能实现一定的功能
1. 元注解
- 元注解:用在注解上的,对注解进行定义约束的注解
- Jar包位置:
java.lang.annotation
常用元注解 | 描述 |
---|---|
@Retention | 标识注解的生命周期,(即标识注解的有效级别/范围) |
@Documented | 标识注解是否包含在javadoc中。 |
@Target | 标记注解的使用范围(即标识注解可用于类上,或方法上…) |
@Inherited | 标记注解能被继承(自动定义的注解@A有@Inherited,则父类Car使用@A注解是,继承父类的BaoMa子类,也有@A注解) |
(1)@Retention
@Retention(value={RetentionPolicy.SOURCE})
/*
● RetentionPolicy.SOURCE : 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。@Override, @SuppressWarnings都属于这类注解。
● RetentionPolicy.CLASS : 在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
● RetentionPolicy.RUNTIME : 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
*/
(2)@Target
@Target(value={ElementType.TYPE,ElementType.FIELD})
/*
● ElementType.CONSTRUCTOR :用于描述构造器。
● ElementType.FIELD :成员变量、对象、属性(包括enum实例)。
● ElementType.LOCAL_VARIABLE: 用于描述局部变量。
● ElementType.METHOD : 用于描述方法。
● ElementType.PACKAGE :用于描述包。
● ElementType.PARAMETER :用于描述参数。
● ElementType.ANNOTATION_TYPE:用于描述参数
● ElementType.TYPE :用于描述类、接口(包括注解类型) 或enum声明。
*/
2. 注解定义语法
- 用
@interface
声明是一个注解; - 访问修饰符必须为public,不写默认为public;
- 注解内元素的类型只能是基本数据类型
- 若注解内只有一个元素,定义为value(便于使用注解)
- 注解内元素定义格式
[public] 数据类型 元素名();
,跟接口内定义方法很像,但()
内不可有参数 default
赋予元素默认值,格式[public] 数据类型 元素名() default 值;
- 不给元素默认值,后面使用注解则必须赋值
@Target(xxxxx)
@Retention(xxx)
public @interface MyAnnotation {
public String name();
int age() default 18; //赋予默认值
int[] array();
}
3. 注解使用语法
-
根据注解@Target的限制用于类/方法/属性上
-
若注解没有元素或注解没元素均有默认值,则注解的时候可以省略()
-
若注解只有一个元素,且命名为
value()
,则使用时可以用@注解名(注解值)
格式 -
若注解内元素为数组,则使用格式为
@注解名(元素名={值1,值2})
-
使用注解时,对多个元素赋值,元素间用逗号
,
隔开
@MyAnnotation(name="Amy",array={1,2})
反射
反射(Reflection):是计算机程序在运行时,可以针对某类(或方法,属性等)进行访问,检测或修改的一种能力; 是java被视为动态语言的关键,反射机制允许代码在执行期间借助于Reflection Api取得任何类的内部信息,并可直接操作类中的所有属性和方法(即便属性或方法为private也可操作)
反射常用类 | 描述 |
---|---|
java.lang.Class | 代表一个类 |
java.lang.reflect.Method | 代表类的方法 |
java.lang.reflect.Field | 代表类的成员变量 |
java.lang.reflect.Constructior | 代表类的构造器 |
1. 获取Class类对象的方式
Class.forname("类对象包路径");
类名.class;
实例化对象.getClass();
2. Class类
方法 | 描述 |
---|---|
public T newInstance() | 实例化类对象(调用无参构造) |
public String getName() | 获取包名 |
public String getSimpleName() | 获取类名 |
public Field[] getDeclaredFields() | 获取类中所有的属性 |
public Field getDeclaredField(String name) | 根据属性名name获取指定的属性 |
public Field[] getFields() | 获取类中public修饰的属性 |
public Field[] getDeclaredFields() | 获取类中所有的属性 |
public Method[] getDeclaredMethods() | 获取类中所有的实例方法 |
public Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 根据方法名name和方法形参获取指定方法 |
public Constructor<?>[] getDeclaredConstructors() | 获取类中所有的构造方法 |
public Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 获取类指定的构造方法 |
public Annotation[] getDeclaredAnnotations() | 获取类上注解 |
public ? getDeclaredAnnotation(Class<?> annotationClass) | 获取类上指定注解类型 |
3. Field类
方法 | 描述 |
---|---|
public String getName() | 获取属性名 |
public Class<?> getType() | 获取属性所属类型 |
public void set(Object obj, Object value) | 设置属性值 |
public Object get(Object obj) | 读取属性值 |
public Annotation[] getDeclaredAnnotations() | 获取属性上注解 |
public ? getDeclaredAnnotation(Class<?> annotationClass) | 获取属性上指定注解类型 |
4. Method类
方法 | 描述 |
---|---|
public String getName() | 返回方法名 |
public Class<?> getReturnType() | 获取方法返回值类型 |
public Object invoke(Object obj, Object… args) | 调用方法 |
public Annotation[] getDeclaredAnnotations() | 获取方法上注解 |
public ? getDeclaredAnnotation(Class<?> annotationClass) | 获取方法上指定注解类型 |
5. Constructor类
方法 | 描述 |
---|---|
public String getName() | 返回构造方法名 |
public T newInstance(Object … initargs) | 创建对象【参数为创建对象的数据】 |
public Annotation[] getDeclaredAnnotations() | 获取构造器上注解 |
public ? getDeclaredAnnotation(Class<?> annotationClass) | 获取构造器上指定注解类型 |
自定义注解+反射示例
1. 自定义注解
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {
int data() default 18; //赋予默认值
}
2. 使用注解的类
public class User {
@MyAnnotation
private String username = "Mike";
private Integer age ;
}
3. 测试类
-
关键:
-
annotation
注解类是所有注解的父类,可通过强转变为目标注解类型 -
当注解类被实例化后,它的使用和普通类对象基本没区别
-
public class Test {
public static void main(String[] args) throws Exception {
// 获取UserClass类对象
Class<?> aClass = Class.forName("beholer1234.User");
// 获取UserClass类对象中的UsernameField属性类对象
Field username = aClass.getDeclaredField("username");
// 获取UsernameField属性类对象上的所有Annotation注解类对象
Annotation[] annotations = username.getAnnotations();
// 选择第一个Annotation注解类对象强转为MyAnnotation注解类对象,并且赋予myannotation
MyAnnotation myannotation = (MyAnnotation) annotations[0];
// MyAnnotation annotation =
// username.getAnnotation(MyAnnotation.class); //效果一样
// 获取myannotation注解类对象的data()值,并输出
System.out.println(annotation.data()); // 结果返回18
}
}