• Java - 反射


    文章目录

    大家好,今天给大家介绍一下java中的反射,在学习web和框架的时候反射是不可或缺的,偏底层的内容会大量使用反射,很重要。


    一 . 什么是反射?

    Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到,那么我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

    Java的反射机制主要依赖于以下几个类:

    1. Class类:表示一个类或接口,在运行时可以通过该类获取该类的构造方法、字段、方法等信息。

    2. Constructor类:表示一个构造方法,可以通过该类创建对象。

    3. Field类:表示类的字段,可以通过该类访问和修改字段的值。

    4. Method类:表示类的方法,可以通过该类调用方法。

     

    二 . 反射的使用

    1.获取class对象

    在Java中,可以通过以下几种方式来获取Class对象:

    1. 使用对象的getClass()方法:每个对象都有一个getClass()方法,可以通过该方法获取该对象所属的类的Class对象。
    1. MyClass obj = new MyClass();
    2. ClassMyClass> clazz = obj.getClass();
    1. 使用类名.class语法:通过类名后面加上".class"来获取该类的Class对象。
    Class<MyClass> clazz = MyClass.class;
    
    1. 使用Class.forName()方法:通过类的全限定名(包名+类名)来获取该类的Class对象。需要注意的是,使用Class.forName()方法时需要提供类的全限定名,并且需要处理ClassNotFoundException异常。
    Class<?> clazz = Class.forName("com.example.MyClass");


     2.获取构造方法

    1.Constructor[] getConstructors() 获取全部构造器(只能获取public修饰的)
    ​​​​​
    2.Constructor[] getDeclaredConstructors()获取全部构造器(只要存在就能拿到)
    
    3.Constructor getConstructor(class... parameterTypes) 获取某个构造器(只能获取public修饰的)
    
    4.Constructor getDeclaredConstructor(Class... parameterTypes) 获取某个构造器(只要存在就能拿到,不管是不是private修饰的)
    
    1. import java.lang.reflect.Constructor;
    2. public class MyClass {
    3. public MyClass() {
    4. }
    5. public MyClass(int value) {
    6. }
    7. public static void main(String[] args) {
    8. try {
    9. // 获取公共的无参构造方法
    10. Constructor constructor1 = MyClass.class.getConstructor();
    11. System.out.println(constructor1);
    12. // 获取公共的有参构造方法
    13. Constructor constructor2 = MyClass.class.getConstructor(int.class);
    14. System.out.println(constructor2);
    15. // 获取所有的构造方法
    16. Constructor[] constructors = MyClass.class.getDeclaredConstructors();
    17. for (Constructor constructor : constructors) {
    18. System.out.println(constructor);
    19. }
    20. } catch (NoSuchMethodException e) {
    21. e.printStackTrace();
    22. }
    23. }
    24. }

    输出结果为:

    1. public com.example.MyClass()
    2. public com.example.MyClass(int)
    3. private com.example.MyClass()

    Constructor类中常用的方法:

    T newInstance(Object....args) 调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
    public void setAccessible(Boolean flag) 设置为true,表示禁止检查访问控制(暴力反射,临时取消权限校验)

     student类:

    1. public class Student {
    2. private String name;
    3. private int age;
    4. public Student() {
    5. }
    6. private Student(String name, int age) {
    7. this.name = name;
    8. this.age = age;
    9. }
    10. public String getName() {
    11. return name;
    12. }
    13. public void setName(String name) {
    14. this.name = name;
    15. }
    16. public int getAge() {
    17. return age;
    18. }
    19. public void setAge(int age) {
    20. this.age = age;
    21. }
    22. @Override
    23. public String toString() {
    24. return "Student{" +
    25. "name='" + name + '\'' +
    26. ", age=" + age +
    27. '}';
    28. }
    29. }
    1. import java.lang.reflect.Constructor;
    2. public class ReflectionExample {
    3. public static void main(String[] args) {
    4. try {
    5. // 获取有参构造方法
    6. Constructor constructor = Student.class.getDeclaredConstructor(String.class, int.class);
    7. // 设置为可访问 暴力反射 临时取消访问检测
    8. constructor.setAccessible(true);
    9. // 调用构造方法创建实例
    10. Student student = constructor.newInstance("John", 20);
    11. System.out.println(student);
    12. } catch (Exception e) {
    13. e.printStackTrace();
    14. }
    15. }
    16. }

     输出

    Student{name='John', age=20}

    3.获取成员变量

     

    在Java中,Class类提供了多个用于获取成员变量的方法。以下是一些常用的方法:

    1. getField(String name):获取指定名称的公共成员变量(包括父类中的公共成员变量)。
    2. getDeclaredField(String name):获取指定名称的成员变量(不包括父类中的成员变量),无论其访问修饰符是什么。
    3. getFields():获取所有的公共成员变量(包括父类中的公共成员变量)。
    4. getDeclaredFields():获取所有的成员变量(不包括父类中的成员变量),无论其访问修饰符是什么。

    1. import java.lang.reflect.Field;
    2. public class MyClass {
    3. public static void main(String[] args) {
    4. try {
    5. // 获取指定名称的公共成员变量
    6. Field field1 = Student.class.getField("name");
    7. System.out.println(field1);
    8. // 获取指定名称的成员变量
    9. Field field2 = Student.class.getDeclaredField("age");
    10. System.out.println(field2);
    11. // 获取所有的公共成员变量
    12. Field[] fields1 = Student.class.getFields();
    13. for (Field field : fields1) {
    14. System.out.println(field);
    15. }
    16. // 获取所有的成员变量
    17. Field[] fields2 = Student.class.getDeclaredFields();
    18. for (Field field : fields2) {
    19. System.out.println(field);
    20. }
    21. } catch (NoSuchFieldException e) {
    22. e.printStackTrace();
    23. }
    24. }
    25. }

    Field类中常用的方法 

    1.void set(Object obj,Object value) 为obj对象里的成员变量赋值为value

    2.Object get(Object obj) 取出obj对象中的值

    3.public void setAccessible(Boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)

    1. import java.lang.reflect.Constructor;
    2. import java.lang.reflect.Field;
    3. public class ReflectionExample {
    4. public static void main(String[] args) {
    5. try {
    6. // 使用反射调用构造方法创建实例
    7. Constructor constructor = Student.class.getDeclaredConstructor(String.class, int.class);
    8. constructor.setAccessible(true);
    9. Student student = constructor.newInstance("John", 20);
    10. System.out.println(student);
    11. // 使用反射获取和修改成员变量的值
    12. Field nameField = Student.class.getDeclaredField("name");
    13. nameField.setAccessible(true);
    14. nameField.set(student, "Tom");
    15. Field ageField = Student.class.getDeclaredField("age");
    16. ageField.setAccessible(true);
    17. int age = (int) ageField.get(student);
    18. ageField.set(student, age + 1);
    19. System.out.println(student);
    20. } catch (Exception e) {
    21. e.printStackTrace();
    22. }
    23. }
    24. }

    输出结果为:

    1. Student{name='John', age=20}
    2. Student{name='Tom', age=21}

    4.获取成员方法

    java.lang.Class类中用于获取成员方法的方法:

    1. public Method getMethod(String name, Class... parameterTypes):根据方法名和参数类型获取指定的公共成员方法(包括继承的方法)。

    2. public Method[] getMethods():获取所有的公共成员方法(包括继承的方法)。

    3. public Method getDeclaredMethod(String name, Class... parameterTypes):根据方法名和参数类型获取指定的成员方法(不包括继承的方法)。

    4. public Method[] getDeclaredMethods():获取所有的成员方法(不包括继承的方法)。


     和上面都一样,不再多说,我们来看看 Method中的方法

    1. public Object invoke(Object obj, Object... args):通过反射调用该方法,传入指定对象和参数,并返回方法的返回值。

    2. public Class getReturnType():获取方法的返回类型,返回一个Class对象。

    3. public String getName():获取方法的名称。

    4. public int getModifiers():获取方法的修饰符,返回一个代表修饰符的整数。

    5. public Class[] getParameterTypes():获取方法的参数类型,返回一个Class对象数组。

    6. public void setAccessible(boolean flag):设置方法是否可访问。


     student类中加上该方法用来演示invoke方法


    总结

    今天的内容就到这了,大家好好理解。

  • 相关阅读:
    OceanBase 数据库入门知识
    【经验分享】Ubuntu如何设置swap交换
    Python小游戏14——雷霆战机
    【Linux杂货铺】调试工具gdb的使用
    本地部署mini k8 cluster
    Python 推导式
    Sentinel整合RestTemplate
    设计模式 代理模式
    【UE 材质】制作加载图案(2)
    基于SSH开发网上电器(购物商城)销售系统
  • 原文地址:https://blog.csdn.net/weixin_73869209/article/details/133704373