• Java的反射


    目录

    反射

    什么是反射?

    举例

    好处:

    java Bean

    反射作业

    反射代码

    属性文件(config.properties)

    读取属性文件


    反射

    什么是反射?

    (1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到类对象之后,再通过类对象进行反编译,从而获取对象的各种信息。

    (2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁

    反射:能够分析类信息的能力叫做反射,那什么是类的信息?

    简单的来说比如 属性、方法、构造器等等。。。

    举例

    1. Class class1 = Class.forName("reflect.Person");
    2. System.out.println(class1);
    3. Field[] fields = class1.getFields();
    4.    for (Field field : fields) {
    5.             System.out.println(field);
    6.       }

    那么一个新的问题就来了,我们明明可以通过new 一个对象来获取类信息,那么我们为什么要使用反射呢?

    我们在这里说一个实际的列子,比如说我们使用的servlet,在servlet当中我们用过jdbc操作,在这个类当中我们引入了一个mysql.jar包,那么这个jar包是怎么起作用的呢,请大家注意,我们的servlet类当中没有main方法,那我们的servlet类是如何启动的呢?如何加载到我们的JVM当中呢?

    答案就是使用了反射,大家看一个东西

     

    从上面可以看到,正是因为有了反射,我们才能将他们加载如JVM当中。

    那么反射是如何工作的呢?

    要想理解反射是如何工作的我们先来看类的生命周期

     

     

    好处:

            1.在程序的运行过程中,来操作这些对象

    1. String str = "123";
    2. str.

    我们对 . 出很多的方法,这其实就是内部使用的是反射机制,你定义了一个字符串,那么他会把字符串的字节码文件加载进内存,在内存当中有一个class类对象,class对象已将所有的方法都抽取出来封装在method[]数组当中,所以我们能够 . 出这么多的程序。

            2.可以解耦,提高程序的可扩展性

             获取class对象的方式

            1.Class.forName("全类名"):将字节码文件加载进内存,返回class对象

    多用于配置文件,将类名定义在配置文件当中,读取文件,加载类

             2.类名.class: 通过类名的class获取

    多用于参数的传递

            3.对象.getClass() :getClass()方法在object类当中定义着

    多用于对象获取字节码的方式

    首先定义一个person类,内部定义好成员变量,构造方法和成员方法

    1. public class Person {
    2.     
    3.     private String nameString;
    4.     private int age;
    5.     
    6.     public Person() {
    7.         
    8.     }
    9.     
    10.     public Person(String nameString, int age) {
    11.         this.nameString = nameString;
    12.         this.age = age;
    13.     }
    14.  
    15.     public String getNameString() {
    16.         return nameString;
    17.     }
    18.  
    19.     public void setNameString(String nameString) {
    20.         this.nameString = nameString;
    21.     }
    22.  
    23.     public int getAge() {
    24.         return age;
    25.     }
    26.  
    27.     public void setAge(int age) {
    28.         this.age = age;
    29.     }
    30.  
    31.     @Override
    32.     public String toString() {
    33.         return "Person [nameString=" + nameString + ", age=" + age + "]";
    34.     }
    35.  
    36. }

    定义测试类

    1. public class refulectDemo1 {
    2.     
    3.     /**
    4.      *      1.Class.forName("全类名"):将字节码文件加载进内存,返回class对象
    5.         2.类名.class:通过类名的class获取
    6.         3.对象.getClass(): getClass()方法在object类当中定义着
    7.      * @throws ClassNotFoundException 
    8.      */
    9.     public static void main(String[] args) throws Exception {
    10.         // 1.Class.forName("全类名"):
    11.         Class class1 = Class.forName("reflect.Person");
    12.         System.out.println(class1);
    13.         
    14.         //2.类名.class:通过类名的class获取
    15.         Class class2 = Person.class;
    16.         System.out.println(class2);
    17.         
    18.         //3.对象.getClass()
    19.         Person person = new Person();
    20.         Class class3 = person.getClass();
    21.         System.out.println(class3);
    22.         
    23.     }
    24.  
    25. }

    用 == 进行比较

    1. System.out.println(class1 == class2);
    2. System.out.println(class2 == class3);

    输出为:

    1. true
    2. true

    结论:

    同一个类加载器加载的文件(*.class)在一次程序运行过程中,只会被加载一次,不论你通过那种方式获取的class对象都是同一个

    class对象常用功能

    1. /*通过反射获取Person类对象*/
    2. Class aClass = Class.forName("com.qcby.reflect.Person");
    3.  
    4. Field[] fields = aClass.getDeclaredFields();
    5. System.out.println("获取Person的所有属性对象");
    6. for (Field field : fields) {
    7.     System.out.println(field);
    8. }
    9. System.out.println("获取Person的age属性对象");
    10. Field age = aClass.getDeclaredField("age");
    11. System.out.println(age);
    12. System.out.println("-------------------------------------\n");
    13.  
    14.  
    15. Constructor[] constructors = aClass.getDeclaredConstructors();
    16. System.out.println("获取Person的所有构造方法");
    17. for (Constructor constructor : constructors) {
    18.     System.out.println(constructor);
    19. }
    20. System.out.println("获取Person的无参构造方法");
    21. Constructor constructor = aClass.getDeclaredConstructor();
    22. System.out.println(constructor);
    23. System.out.println("获取Person的有参构造方法");
    24. Constructor constructor1 = aClass.getDeclaredConstructor(String.class,Integer.class);
    25. System.out.println(constructor1);
    26. System.out.println("-------------------------------------\n");
    27.  
    28. Method[] declaredMethods = aClass.getDeclaredMethods();
    29. System.out.println("获取Person的所有普通方法");
    30. for (Method declaredMethod : declaredMethods) {
    31.     System.out.println(declaredMethod);
    32. }
    33. System.out.println("获取Person的getAge普通方法");
    34. Method getAge = aClass.getDeclaredMethod("getAge");
    35. System.out.println(getAge);
    36. System.out.println("获取Person的getAge普通方法");
    37. Method setAge = aClass.getDeclaredMethod("setAge",Integer.class);
    38. System.out.println(setAge);
    39. System.out.println("-------------------------------------\n");
    40.  
    41. System.out.println("获取Person的全类名");
    42. System.out.println(aClass.getName());
    43. System.out.println("获取Person的类名");
    44. System.out.println(aClass.getSimpleName());

    Field成员变量       

            操作

                    1.设置值

                            void set(Object obj,Object value)

                    2.获取值

                            get(Object obj)

    1.  public static void main(String[] args) throws Exception {
    2.  
    3.         //0.获取Person的Class对象
    4.         Class personClass = Person.class;
    5.         /*
    6.              1. 获取成员变量们
    7.                  * Field[] getFields()
    8.                  * Field getField(String name)
    9.                  * Field[] getDeclaredFields()
    10.                  * Field getDeclaredField(String name)
    11.          */
    12.         //1.Field[] getFields()获取所有public修饰的成员变量
    13.         Field[] fields = personClass.getFields();
    14.         for (Field field : fields) {
    15.             System.out.println(field);
    16.         }
    17.  
    18.         System.out.println("------------");
    19.         //2.Field getField(String name)
    20.         Field a = personClass.getField("a");
    21.         //获取成员变量a 的值
    22.         Person p = new Person();
    23.         Object value = a.get(p);
    24.         System.out.println(value);
    25.         //设置a的值
    26.         a.set(p,"张三");
    27.         System.out.println(p);
    28.  
    29.         System.out.println("===================");
    30.  
    31.         //Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
    32.         Field[] declaredFields = personClass.getDeclaredFields();
    33.         for (Field declaredField : declaredFields) {
    34.             System.out.println(declaredField);
    35.         }
    36.         //Field getDeclaredField(String name)
    37.         Field d = personClass.getDeclaredField("d");
    38.         //忽略访问权限修饰符的安全检查
    39.         d.setAccessible(true);//暴力反射
    40.         Object value2 = d.get(p);
    41.         System.out.println(value2);
    42.  
    43.     }

    忽略安全访问修饰符的安全检查 setAccessible(true) //暴力反射 ---》private

    Constructor访问构造方法  

            *创建对象

                    *T newInstance(Object... initarges)

                    *如果使用空参数构造方法,此操作可以简化:class对象的newInstance方法

    1. public static void main(String[] args) throws Exception {
    2.         //0.获取Person的class对象
    3.         Class personClass = Person.class;
    4.  
    5.         //因为构造器的方法名称是相同的,不同的是参数列表,所以我们可以根据不同的参数列表来找到构造器
    6.         Constructor constructor = personClass.getConstructor(String.class,int.class);
    7.         System.out.println(constructor);
    8.         //创建对象
    9.         Object perObject = constructor.newInstance("张三",20);
    10.         System.out.println(perObject);
    11.         
    12.         System.out.println("-------------------------------");
    13.     
    14.         Constructor constructor1 = personClass.getConstructor();
    15.         System.out.println(constructor1);
    16.         //创建对象
    17.         Object perObject1 = constructor1.newInstance();
    18.         System.out.println(perObject1);
    19.         
    20.         System.out.println("-------------------------------");
    21.         Object o = personClass.newInstance();
    22.         System.out.println(o);
    23.     }

    Method:方法对象

            *执行方法

                    *object invoke(Object object,Object... ages)

            *获取方法名称

                    *String getName:获取方法名

    1. public static void main(String[] args) throws Exception {
    2.         //0.获取Person的class对象
    3.         Class personClass = Person.class;
    4.         
    5.         //获取指定名称的方法,方法无参
    6.         Method eat_method = personClass.getMethod("eat");
    7.         //执行方法
    8.         Person person =new Person();
    9.         eat_method.invoke(person);
    10.         
    11.         //获取指定名称的方法,方法有参
    12.         Method eat_method1 = personClass.getMethod("eat",String.class);
    13.         //执行方法
    14.         eat_method1.invoke(person,"饭");
    15.         
    16.         //获取所有public修饰的方法
    17.         Method[] methods = personClass.getMethods();
    18.         for (Method method : methods) {
    19.             System.out.println(method);
    20.             //获取方法的名称
    21.             String name = method.getName();
    22.             System.out.println(name);
    23.         }
    24.     }

    java Bean

    java bean是java类的一种特殊格式,java bean要求

    1.该类下所有的成员变量都是私有的

    2..每一个私有的变量都有一对方法对他进行操作,分别是get()和set()方法

    3.在set方法当中有一个给成员变量赋值的方法

    反射作业

    作业:给定一个java bean,获取该类的构造方法来构造对象,获取该类的名称和该类中每一个变量的名称和方法的名称,并执行相关方法。给每一个变量赋值,并获取值,执行每一个构造方法,执行相应的方法

    1. public class Student {
    2.     
    3.     private String name;
    4.     private int age;
    5.     private String address;
    6.     public Student(String name,int age,String address) {
    7.         this.address = address;
    8.         this.age = age;
    9.         this.name = name;
    10.     }
    11.     public String getName() {
    12.         return name;
    13.     }
    14.     public void setName(String name) {
    15.         this.name = name;
    16.     }
    17.     public int getAge() {
    18.         return age;
    19.     }
    20.     public void setAge(int age) {
    21.         this.age = age;
    22.     }
    23.     public String getAddress() {
    24.         return address;
    25.     }
    26.     public void setAddress(String address) {
    27.         this.address = address;
    28.     }
    29. }

    反射代码

    1. public class CommonReflect {
    2.  
    3.     //获取该类的名称
    4.     public static void getClassName(Object object) {
    5.         String className = object.getClass().getSimpleName();
    6.         System.out.println("类的名字是:"+className);
    7.     }
    8.     
    9.     //获取类的变量名称
    10.     public static void getField(Object object) {
    11.         Field[] fields = object.getClass().getDeclaredFields();
    12.         for (int i = 0; i < fields.length; i++) {
    13.             System.out.println("成员变量的名称为:"+fields[i].getName());
    14.         }
    15.     }
    16.     
    17.     //获取类的成员方法
    18.     public static void getMethod(Object object) {
    19.         Method[] methods = object.getClass().getDeclaredMethods();
    20.         for (int i = 0; i < methods.length; i++) {
    21.             System.out.println("成员方法的名称:"+methods[i].getName());
    22.         }
    23.     }
    24.     
    25.     //调用该类的成员方法,以get为例
    26.     public static void getAction(Object object) throws Exception {
    27.         //获取到有多少get方法
    28.         Field[] fields = object.getClass().getDeclaredFields();
    29.         for (int i = 0; i < fields.length; i++) {
    30.             String fieldName = fields[i].getName();
    31.             String fistfont = fieldName.substring(0,1).toUpperCase();
    32.             String methodname = "get"+fistfont+fieldName.substring(1);
    33.             Method method = object.getClass().getMethod(methodname);
    34.             System.out.println("get的输出结果:"+method.invoke(object));
    35.         }
    36.  
    37.     }
    1.  public static void main(String[] args) throws Exception {
    2.         Object studentObject = Student.class.getConstructor(String.class,int.class,String.class).newInstance("张三",20,"保定");
    3.         getClassName(studentObject);
    4.         getField(studentObject);
    5.         getMethod(studentObject);
    6.         getAction(studentObject);
    7.         
    8.     }
    9. }

    属性文件(config.properties)

    1. reflect.className=com.qcby.reflect.Person
    2. reflect.MethodName=getAge

    读取属性文件

    1. //1、加载配置文件
    2.   //1.1、创建properties对象
    3.  Properties properties = new Properties();
    4.   //1.2、加载配置文件
    5.   ClassLoader classLoader = Person.class.getClassLoader();
    6.   InputStream input = classLoader.getResourceAsStream("com/qcby/reflect/config.properties");
    7.   properties.load(input);
    8.  
    9.   //2、获取配置文件当中定义的数据源
    10.   String className = properties.getProperty("reflect.className");
    11.   String methodName = properties.getProperty("reflect.MethodName");
    12.     
    13.  //反射代码
    14.   Class clz = Class.forName(className);
    15.   Object object = clz.getDeclaredConstructor(String.class,Integer.class,Integer.class).newInstance("gs",23,5);
    16.   Method method = clz.getDeclaredMethod(methodName);
    17.   System.out.println(method.invoke(object));

  • 相关阅读:
    恒峰智慧科技-太阳能语音杆:一杆多用,节能环保新选择!
    Exception : Content-Type cannot contain wildcard type ‘*‘
    Dubbo分组聚合
    EditorConfig + Prettier + ESLint 代码规范化
    关于RSA常见的错误理解
    10 特征向量与特征值
    智慧海关集装箱RFID物流运输管理系统解决方案
    pdf如何压缩文件大小?pdf文件在线压缩方法介绍
    vulnhub Potato: 1
    基础设施即代码(IAC),Zalando Postgres Operator UI 入门
  • 原文地址:https://blog.csdn.net/LiZhen314/article/details/126159256