• Java 的反射


          反射多用于 JDBC 中的加载驱动程序 Class.forName("com.mysql.jdbc.Driver"); Struts 的MVC、Hibernate 中的 ORM Spring 中的 IOC 还有一些其他框架等等。
          好处: 能够动态的创建对象和编译且能够访问某个 类中的所有(包括私有) 属性方法及对象的属
    性方法并进行调用,比较灵活,这样 也有利于降低类间的耦合度;
          缺点: 破坏了类的封装性和对象的完整性

    需要掌握的知识点:

    • 理解 Class
    • 理解 Java 的类加载机制
    • 学会使用 ClassLoader 进行类加载
    • 理解反射的机制
    • 掌握 ConstructorMethodField 类的用法

    一、Class 类:

         1 、对象照镜子后可以得到的信息:某个类的数据成员名、方法和构造器、某 个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。
         2、Class 对象只能由系统建立对象
         3、一个类在 JVM 中只会有一个 Class 实例,每个类的实例都会记得自己是由哪个 Class 实例所生成
         4、获取 Class 对象的方式:
                   Class c1=null;
              (1)通过类的 class 属性获取,这种方法最可靠、程序性能更高
                    类名.class
                    c1=Person.class;
              (2)通过对象调用 getClass()方法获取
                     Object obj=new Person();
                    c1=obj.getClass();
               (3)通过全类名来获取(用的较多)
                      String className=“com.info.Person”;
                      c1=Class.forName(className)
             5、Class 类的常用方法
    方法名
    功能说明
    static Class forName(String name)
    返回指定类名 name 的 Class 对象
    Object newInstance()
    调用缺省构造函数,返回该 Class 对象的一个实例
    Object newInstance(Object []args)
    调用当前格式构造函数,返回该 Class 对象的一个
    实例
    getName()
    返回此 Class 对象所表示的实体(类、接口、数组
    类、基本类型或 void)名称
    Class getSuperClass()
    返回当前 Class 对象的父类的 Class 对象
    Class [] getInterfaces ()
    获取当前 Class 对象的接口
    ClassLoader getClassLoader()
    返回该类的类加载器
    Class getSuperclass()
    返回表示此 Class 所表示的实体的超类的 Class
                 (1) Object newInstance()方法的使用:
                             Class c2=null;
                            c2=Class.forName("com.info.Person");
                            Object obj=c2.newInstance();//调用类的无参的构造器
                            System.out.println(obj);
             【注意】在定义类时一定要声明无参的构造器,给反射使用

    二、ClassLoader

          类加载器是用来把类(class)装载进 JVM 的。JVM 规范定义了两种类型的类加载器:
          启动类加载器(bootstrap)和用户自定义加载器(user-defined class loader)。 JVM 在运
          行时会产生 3 个类加载器组成的初始化加载器层次结构 ,如下图所示:
              
           示例:
    1. //1、获取一个系统的类加载器
    2. ClassLoader loader=ClassLoader.getSystemClassLoader();
    3. System.out.println(loader);
    4. //2、获取系统类加载器的父类加载器
    5. loader=loader.getParent();
    6. System.out.println(loader);
    7. //3、测试当前类是由哪个类加载器加载的:
    8. loader=Class.forName("com.info.TestClass").getClassLoader();
    9. System.out.println(loader);
    三、Reflection (反射)是 Java 被视为动态语言的关键,反射机制允许程序在执行期借 助于 Reflection API 取得任何类的內部信息,并能直接操作任意对象的内部属性及方法。
    Java反射机制主要提供了以下功能:
    • 在运行时构造任意一个类的对象
    • 在运行时获取任意一个类所具有的成员变量和方法
    • 在运行时调用任意一个对象的方法(属性)
    • 生成动态代理

        1Field类用于操作类的属性 :

    1. Class<?> c1 = Class.forName("com.info.Person");
    2. Object s1 = c1.newInstance();
    3. // 获取某个属性
    4. Field field = c1.getDeclaredField("name");
    5. // 该属性设置为可访问
    6. field.setAccessible(true);
    7. System.out.println("field = " + field + " , " + field.get(s1));
    8. // 获取指定类的所有属性
    9. Field[] fields = c1.getDeclaredFields();
    10. for (Field f : fields) {
    11. f.setAccessible(true);
    12. System.out.println(f.getName() + " = " + f.get(s1));
    13. }

         2、Method类用于操作类的方法

    1. Class<?> c1 = Class.forName("com.info.Person");
    2. Object s1 = c1.newInstance();
    3. // 获取某个类的指定含参方法
    4. Method m2 = c1.getDeclaredMethod("setId", String.class);
    5. m2.invoke(s1, "001");
    6. // 获取某个类的指定无参方法
    7. Method m1 = c1.getDeclaredMethod("getId");
    8. System.out.println(m1.invoke(s1));
    9. System.out.println("=======================");
    10. // 获取指定类的所有方法
    11. Method[] methods = c1.getDeclaredMethods();
    12. for (Method method : methods) {
    13. method.setAccessible(true);
    14. System.out.println(method.getName());
    15. }
    16. System.out.println("=======================\n")
           3 Constrctor类用于操作类的构造器:
    1. Class<?> c1 = Class.forName("com.info.Person");
    2. // 获取带有指定参数列表的构造方法的Constructor对象
    3. Constructor<?> cs = c1.getDeclaredConstructor(String.class,
    4. String.class);
    5. Object s1 = cs.newInstance("001","李四");
    6. System.out.println(s1);
    7. // 获取指定类的所有构造器
    8. Constructor<?>[] constructors = c1.getDeclaredConstructors();
    9. for (Constructor<?> constructor : constructors) {
    10. System.out.println("constructor = " + constructor);
    11. }
    总结
       1 、所有类的对象其实都是 Class 的实例。
       2 Class 实例化其他类的对象的时候,一定要保留默认的无参构造方法。
       3 、加载某个类的 3 种常用方式:
              a) Class.forName(" 类的完整路径 ")
              b) 类名 .class
              c) obj.getClass()
       4 、反射的常用的两步:
             Class<?> c1 = Class.forName(" 类的完整路径 ");
             Object t = c1.newInstance();

  • 相关阅读:
    第十八章Swing程序设计总结
    Python(1):Python基础知识
    centos7 mysql5.7离线安装
    扩展翡蜀定理问题
    解决php中通过exec调用python脚本报ModuleNotFoundError错误
    【C语言】冒泡排序升级版---适用任意类型
    请解释一下React中的条件渲染(conditional rendering)。
    vue3使用腾讯地图选择地点
    如何搭建APP分发平台分发平台搭建教程
    融入Facebook的世界:探索数字化社交的魅力
  • 原文地址:https://blog.csdn.net/m0_37911706/article/details/125305914