注解与反射

注解

  • 作用:
    • 不是程序本身,可对程序做出解释
    • 可以被其他程序读取(如:编译器)
    • 可附加在package,class,method,field等上面,相当于给他们添加额外辅助信息
    • 可通过反射机制编程实现访问

内置注解

常见的:

都定义在java.lang包下

  • @Override
  • @Deprecated
  • @SuppressWarning:用来抑制编译时的警告,但后面括号中需要参数

元注解

  • 作用就是负责注解其他注解
  • Java定义了4个标准的meta-annotation类型,用来对其他annotation类型做说明(@Target @Document @Inherited @Retention)
    • @Target:描述注解使用范围
    • @Retention:需要在什么级别保存该注释信息,用于描述注解的生命周期 SOURCE< CLASS < RUNTIME
      只有在运行时注解还有效,这样才能读取到
    • @Document:说明该注解将被包含在javadoc中
    • @Inherited:说明子类可以继承父类中的该注解

例:@Target注解源码

package java.lang.annotation;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    //表示该注解的参数
    ElementType[] value();
}

public enum ElementType {
    //可在类上起作用
    TYPE,

    //在一个字段上起作用
    FIELD,

    //可在方法上起作用
    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
}

RetentionPolicy也是枚举类

自定义注解

  • 格式 public @interface 注解名
  • 其中每个方法实际上声明了一个配置参数
  • 方法名称就是参数名称
  • 返回值类型就是参数类型(返回值只能是基本类型,Class,String ,enum)
  • 可以通过default来声明参数默认值
  • 如果只有一个参数成员,一般参数名为value(value才可以省略参数名,直接赋值)
  • 注解元素必须要有值,定义注解元素时,经常使用空字符串,0作默认值

反射

允许对构造方法,成员变量,成员方法的信息进行编程访问

idea的自动提示功能就是用反射来实现的

其中红色的为获取,蓝色的为解剖操作,获取字段构造方法成员方法是从class文件中获取的,所以首先要获取class对象

在这里插入图片描述

获取class对象

以下三种方式获得的class对象,为同一个

  • //使用全类名
    Class.forName("全类名");   //使用的最多
    //在就源代码阶段可以使用,   .java --> .class期间
    
  • Student.class();  //一般当做参数进行传递
    //加载阶段就可以使用    获取到字节码文件后将其加载进内存
    
  • Student s = new Student();
    s.getClass();   //当我们已经有了这个类的对象时才可以使用
    //到运行阶段才可以使用    创建对象后
    

获取构造方法

Class c1 = Class.forName("reflect.Student");

//获取所有公共构造方法
Constructor[] constructors = c1.getConstructors();
for (Constructor c : constructors) {
    System.out.println(c);
}
System.out.println("----------");
//获取任意权限构造方法
Constructor[] con = c1.getDeclaredConstructors();
for (Constructor c: con) {
    System.out.println(c);
}
System.out.println("-----------");

//获取单个公共构造方法
Constructor constructor = c1.getConstructor(int.class,String.class);
System.out.println(constructor);
System.out.println("--------------");
//获取单个任意权限构造方法
Constructor declaredConstructor = c1.getDeclaredConstructor(int.class);
System.out.println(declaredConstructor);

使用通过反射获得的构造方法创建对象

//括号中的参数要与使用的构造方法相对应
//若权限不够,可以暴力反射
con.setAccessible(true);   //临时取消权限校验
Student s = (Student) con.newInstance(12, "lisi");

获取成员变量

Class<?> cl = Class.forName("reflect.Student");
Field[] fields = cl.getDeclaredFields();
for (Field f : fields) {
    System.out.println(f);
}
//获取指定字段(任意权限)
Field age = cl.getDeclaredField("age");
System.out.println(age);

获取成员变量信息

//获取字段权限
int modifiers = age.getModifiers();
System.out.println(modifiers);

//获取字段数据类型
Class<?> type = age.getType();
System.out.println(type);

//获取字段名
String name = age.getName();
System.out.println(name);

//获取成员变量记录的值
//如果访问成员变量的权限不够,可以暴力反射
Student stu = new Student("李四");
stu.setAge(78);
age.setAccessible(true);
Object o = age.get(stu);
System.out.println(o);

//修改成员变量记录的值
age.set(stu,13);
Object o1 = age.get(stu);
System.out.println(o1);

获取成员方法

Class<?> cl = Class.forName("reflect.Student");

//获取指定方法,参数1:方法名   后面的参数:方法形参(用来区别重载方法)
Method method = cl.getDeclaredMethod("eat", String.class);
System.out.println(method);

执行获取到的方法

/**
 * 执行当前方法 invoke
 * 参数1:执行方法的对象
 * 参数2:调用方法传递的参数
 * 返回值:没有就不用获取
 */
Student stu = new Student();
method.setAccessible(true);
method.invoke(stu,"zhouzhou");

作用

  • 获取一个类里面所有的信息,获取到了之后,再执行其他的业务逻辑
  • 结合配置文件,动态的创建对象并调用方法
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值