java反射与自定义注解

自定义注解

注解(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. 注解定义语法

  1. @interface声明是一个注解;
  2. 访问修饰符必须为public,不写默认为public;
  3. 注解内元素的类型只能是基本数据类型
  4. 若注解内只有一个元素,定义为value(便于使用注解)
  5. 注解内元素定义格式[public] 数据类型 元素名();,跟接口内定义方法很像,但()内不可有参数
  6. default赋予元素默认值,格式[public] 数据类型 元素名() default 值;
  7. 不给元素默认值,后面使用注解则必须赋值
@Target(xxxxx)
@Retention(xxx)
public @interface MyAnnotation {
        public String name();
        int age() default 18; //赋予默认值
        int[] array();
}

3. 注解使用语法

  1. 根据注解@Target的限制用于类/方法/属性上

  2. 若注解没有元素或注解没元素均有默认值,则注解的时候可以省略()

  3. 若注解只有一个元素,且命名为value(),则使用时可以用@注解名(注解值)格式

  4. 若注解内元素为数组,则使用格式为@注解名(元素名={值1,值2})

  5. 使用注解时,对多个元素赋值,元素间用逗号,隔开

@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
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值