Java中的反射机制

1.反射(Reflection)的定义

指程序在运行期间可以获取到一个对象的全部信息。

2.java中的反射有何特别之处

反射使得Java程序在运行时可以调用反射API获取任何类的内部信息(比如成员变量,成员方法,构造器,接口,父类等),并且可以操作类的实例对象的属性以及方法。 

在Java程序中,JWM加载完一个类后,在堆内存中就会产生该类的一个class对象,并且该class对象是唯一的,这个Class对象包含了该类的完整结构信息。

3.获取class类的实例

// 1 通过类名.class
Class<Student> studentClass1 = Student.class;
System.out.println(studentClass1.hashCode());
// 2 通过Class.forName("类的全类名")  会抛出类未找到异常
Class<?> studentClass2 = Class.forName("com.example.reflect_test.reflect.Student");
System.out.println(studentClass2.hashCode());
// 3 通过对象.getClass获得
Class<? extends Student> studentClass3 = new Student().getClass();
System.out.println(studentClass3.hashCode());
// 4 获取父类实例
Class<? super Student> superclass = studentClass1.getSuperclass();

4.获取该类的属性,方法,接口,父类等

1.获取类名

String name = studentClass1.getName();              //全类名
String simpleName = studentClass1.getSimpleName();  //单纯类名

2.获取属性(public)

studentClass1.getField("username");           //指定属性
Field[] fields = studentClass1.getFields();   // 获取所有属性

3.获取属性(public和private)

Field username = studentClass1.getDeclaredField("username");
Field[] declaredFields = studentClass1.getDeclaredFields();

 4.获取方法(public) 包括父类的方法

// 无参
Method add = studentClass1.getMethod("add");     // 指定方法
Method[] methods = studentClass1.getMethods();   // 所有方法

//有参
Method declaredMethod = studentClass1.getDeclaredMethod("add",String.class,String.class);
declaredMethod.invoke(student,"111","222");

5.获取方法(public和private构造方法) 不包括父类的方法

Method declaredMethod = studentClass1.getDeclaredMethod("add");
Method[] declaredMethods = studentClass1.getDeclaredMethods();

6.获取类的构造器 (public构造方法)

Constructor<Student> constructor1 = studentClass1.getConstructor(String.class,String.class);
Constructor<?>[] constructors = studentClass1.getConstructors();

7.获取类的构造器 (public和private构造方法)

Constructor<Student> declaredConstructor = studentClass1.getDeclaredConstructor(String.class, String.class);

8.获取父类

Class<? super Student> superclass = studentClass1.getSuperclass();

9.获取接口

Class<?>[] interfaces = studentClass1.getInterfaces();

5.利用反射创建对象

1.使用newInstance创建(其本质上还是通过无参构造方法创建, 前提是类要有一个无参的public的构造方法)

Student student = studentClass1.newInstance();

2.利用类的构造器创建对象,无论构造方法是无参还是有参,私有还是公有

Constructor<Student> declaredConstructor = studentClass1.getDeclaredConstructor(String.class,String.class);  //构造方法参数类型
// 若该构造方法是私有的,如下设置关闭检测
declaredConstructor.setAccessible(true);
Student student = declaredConstructor.newInstance("lisi","wangwu");// 构造方法参数

6.通过反射调用普通方法

  • 无参
// 1.获取该方法实例
Method declaredMethod = studentClass1.getDeclaredMethod("add");
// 如果该方法是私有的,如下设置关闭检测,提高性能
declaredMethod.setAccessible(true);
// 2.收件利用newInstance或构造器创建对象
Student student = studentClass1.newInstance();
// 3.使用invoke执行该方法(第一个参数是实例对象,第二个是方法传入参数)
declaredMethod.invoke(student,null); 
  • 有参
// 1.获取该方法实例 (方法名+参数类型)
Method declaredMethod = studentClass1.getDeclaredMethod("add",String.class,String.class);
// 如果该方法是私有的,如下可设置可访问标志
declaredMethod.setAccessible(true);
// 2.利用newInstance或构造器创建对象
Student student = studentClass1.newInstance();
// 2.使用invoke执行该方法(第一个参数是实例对象,第二个是方法传入参数)
declaredMethod.invoke(student,"111","222");

7.通过反射操作属性

// 1.获取属性实例
Field username = studentClass1.getDeclaredField("username");
// 如果该属性是私有的,如下设置关闭权限检测
username.setAccessible(true);
// 2.获取对象实例
Student student = studentClass1.newInstance();
// 设置属性值
username.get(student);
// 获取属性值
username.set(student,"李四");

8.通过反射获取注解

8.1 读取类上的注解

当作用于类上时,使用类对象.getAnnotation得到注解类型,然后就可以获取变量信息了

// 自定义一个注解
@Target(ElementType.TYPE) // 该注解用于类上
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    String username();
    int age();
}

@MyAnnotation(username = "lisi",age = 20)
class Student1 {
    
}

 使用反射获取注解的变量

// 首先获取类对象
Class<Student1> student1Class = Student1.class;
// 通过 类对象.getAnnotation 获取注解类型
MyAnnotation annotation = student1Class.getAnnotation(MyAnnotation.class);
// 获取变量信息
annotation.username();
annotation.age();

8.2 读取方法上的注解

当作用于方法上时,使用方法类型实例.getAnnotation得到注解类型

@Target(ElementType.METHOD) // 该注解用于方法上
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    String username();
    int age();
}

class Student1 {
    @MyAnnotation(username = "lisi",age = 20)
    public void add() {

    }
}

获取注解的变量 

Class<Student> studentClass = Student.class;
// 得到方法类型
Method add = studentClass.getDeclaredMethod("add");
// 方法类型实例.getAnnotation 获取注解
MyAnnotation annotation = add.getAnnotation(MyAnnotation.class);
// 注解里的变量
annotation.username();
annotation.age();

9.注解

自定义一个注解

@Target(ElementType.TYPE)            //指定注解的生命周期(只在属性上生效)
@Retention(RetentionPolicy.RUNTIME)  //指定注解可以应用的目标元素
@interface Order {
    String value() default "";  //这是一个属性,并非方法,注解中比较特殊,加了括号
}

注解的生命周期分类

  • ElementType.TYPE:类、接口、枚举。
  • ElementType.FIELD:字段。
  • ElementType.METHOD:方法。
  • ElementType.PARAMETER:方法参数。
  • ElementType.CONSTRUCTOR:构造函数。
  • ElementType.LOCAL_VARIABLE:局部变量。
  • ElementType.ANNOTATION_TYPE:注解类型。
  • ElementType.PACKAGE:包。

注解可以应用的目标元素

  • RetentionPolicy.SOURCE:注解仅在源代码中保留,编译时会被丢弃。
  • RetentionPolicy.CLASS:注解在编译时被保留,但在运行时不可访问。
  • RetentionPolicy.RUNTIME:注解在运行时保留,可以通过反射机制访问。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

去北极避暑~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值