首页 > 编程语言 >Java-Day-33 ( 引出反射 + 反射机制 + 反射的优缺点 )

Java-Day-33 ( 引出反射 + 反射机制 + 反射的优缺点 )

时间:2023-07-20 16:01:17浏览次数:28  
标签:反射 Java 33 Dog Class 对象 方法 hello

Java-Day-33

引出反射

( reflection )

  • 引出

    • 传统 new 方法调用其方法:

      Dog dog = new Dog();
      dog.hello();
      
    • 但若要根据以下配置文件指定信息,创建 Dog 对象并调用方法 hello:

      classfullpath=com.zyz.Dog
      method=hello
      
    • 使用 Properties 类,可以读写配置文件

      Properties properties = new Properties();
      properties.load(new FileInputStream("src\\main\\resources\\zyz.properties"));
      String classfullpath = properties.get("classfullpath").toString();
      String methodName = properties.get("method").toString();
      System.out.println("classfullpath=" + classfullpath); // com.zyz.Dog
      System.out.println("methodName=" + methodName); // hello
      
    • 传统的 new 方法行不通

    • 但这样的需求在学习框架时有很多,即通过外部文件配置,在不修改源码的情况下来控制程序,也符合设计模式的 ocp 原则

      • ocp 原则即开闭原则:不修改源码来扩展功能
  • 使用反射机制解决

    • 加载类,返回 Class 类型的对象 cls

      Class cls = Class.forName(classfullpath); // 上面读写到的classfullpath
      
    • 通过 cls 得到加载的类 com.java.Dog 的对象实例

      Object o = cls.newInstance();
      System.out.println(o.getClass()); // (运行类型)class com.zyz.Dog
      
    • 这样的话想调用方法就要强转成 Dog,才能 o.hello(); 调用,但目前需要的是在不知道其有叫 hello 方法的情况下调用 zyz.properties 配置文件的 method 方法:

    • 通过 cls 得到你加载的类的方法名为 hello 的方法代表的对象 ( 即,在反射中,可以把方法也视为对象 —— 万物皆对象 )

      Method method = cls.getMethod(methodName); // 上面读写到的methodName
      
    • 通过 method 调用方法:即,通过方法对象来实现调用方法

      method.invoke(o);
      // 传统方法是:对象.方法(); 而反射机制是:方法.invoke(对象)
      
    • 这样的话,想要变更调用的方法只需要更改配置文件里的 method=xxx 即可,不用更改源码

      • 但传统的 new 的方法需要直接在源码 hello ——> xxx,要改源码

反射机制

  • 反射机制允许程序在执行期间借助于 Reflection API 取得任何类的内部信息 ( 比如成员变量,构造器,成员方法等等,如刚才用到的 newInstance、getMethod、invoke ),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到

  • 加载完类之后,在堆中就产生了一个 Class 类型的对象 ( 一个类只有一个叫 Class 的对象 ),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以形象的称之为 —— 反射

    • 就像前面的 cls 就是 Class 类型的也叫 Class 的对象
  • Java 程序在计算机有三个阶段:( 编译阶段,运行阶段,加载阶段, )

    • 代码阶段 / 编译阶段。如:Dog 类,内含属性、构造器、方法等 —— ( Javac 编译 ) ——> Dog.class 字节码文件,同样内含属性、构造器、方法等
    • Runtime 运行阶段。new Dog()
    • Class 类阶段 ( 加载阶段 )。在 new 后会从字节码文件通过类加载器 ClassLoad 开始加载字节码文件 ( 此处类加载器就体现了反射 ),生成一个 Class 类对象 ( 在堆里 ),同样内含成员变量 Field[]、构造器Constructor[]、成员方法 Method[] 等 ( 因为可能有多个所以都为数组 )
      • 得到对象后就可以在运行阶段创建并执行对象方法、操作属性等
    • 再回到 Class 类阶段后就生成了 Dog 对象了 ( new 的在堆中 ),该对象知道是属于哪个 Class 对象的 ( 加载 ——> 运行 ——> 加载 ) 相互联系
  • Java 反射机制可以完成

    • 在运行时判断任意一个对象所属的类
    • 在运行时构造任意一个类的对象
    • 在运行时得到任意一个类所具有的成员变量和方法
    • 在运行时调用任意一个对象的成员变量和方法
    • 生成动态代理
  • 反射相关的主要类 ( 类中都把对应的 xx 变成了各个对象 )

    • java.lang.Class:代表一个类,其中 Class 对象表示某个类加载后在堆中的对象

    • java.lang.reflect.Method:代表类的方法,其中 Method 对象表示某个类的方法

    • java.lang.reflect.Field:代表类的成员变量,其中 Field 对象表示某个类的成员变量

      // o是上面实例化的对象实例
      Field nameField = cls.getField("age");
      System.out.println(nameField.get(o)); // 传统常用:对象.方法(..)  此处反射:对象.方法(..对象..)
      // 注意要共有public的才可以,私有和默认的都不行
      // 突出的就是一个“反”字
      
    • java.lang.reflect.Constructor:代表类的构造方法,其中 Constructor 对象表示构造器

      Constructor constructor = cls.getConstructor(); // 括号中可以指定构造器参数类型,此处返回的是无参构造器
      //        sout:public com.zyz.Dog()
      //        如果是要构造器:public Dog(String name){..}的:
      Constructor constructor2 = cls.getConstructor(String.class); // 有形参的构造器
      //        sout:public com.zyz.Dog(java.lang.String)
      

反射的优缺点

  • 优点:可以动态的创建和使用对象 ( 也是框架底层核心 ),使用灵活,没有反射机制,框架技术就失去底层支撑

  • 缺点:使用反射基本是解释执行,对执行速度有影响

    • 证明就先后获取时间做差:System.currentTimeMillis();

    • 普通的 for 循环调用上千万次 new 了的 Dog 类中的 hello 方法

    • 普通的 for 循环调用同上千万次反射的 hello 方法

      Method hello = cls.getMethod("hello"); 
      // for 循环里
      hello.invoke(o);
      
    • 反射时间远远大于 new 方法的调用

  • 反射调用优化 —— 关闭访问检查 ( 能稍加快一下速度,提提效率 )

    • Method 和 Field、Constructor 对象都有 setAccessible() 方法

    • setAccessible 作用是启动和禁用访问安全检查的开关

    • 参数值为 true 表示反射的对象在使用时取消访问检查,提高反射的效率。参数值为 false 则表示反射的对象执行访问检查

      Method hello = cls.getMethod("hello"); 
      hello.setAccessible(true); // 在中间,使得反射调用方法时,取消访问检查
      hello.invoke(o);
      

标签:反射,Java,33,Dog,Class,对象,方法,hello
From: https://www.cnblogs.com/zhu-ya-zhu/p/17568630.html

相关文章

  • javascript中json 对象 数组之间相互转化的示例
    在JavaScript中,你可以使用JSON.stringify()将JSON对象转换为JSON字符串,使用JSON.parse()将JSON字符串转换为JSON对象。而要将JSON对象转换为数组,可以使用Object.values()方法,而要将数组转换为JSON对象,可以使用Array.reduce()方法。下面是这些转换的示例代码:将JSON对象转换为JSON......
  • 上班摸鱼刷算法-Java-hot100-[21]合并两个有序链表
    //将一个链表插入到另一个链表中classSolution{publicListNodemergeTwoLists(ListNodelist1,ListNodelist2){if(list1==null){returnlist2;}if(list2==null){returnlist1;}retur......
  • java 文件上次设置编码
    Java文件设置编码在Java编程中,文件编码是一个非常重要的概念。它决定了文件中的字符是如何被存储和解释的。如果文件编码设置不正确,可能导致乱码或无法正确读取文件内容。因此,在处理文本文件时,正确设置文件编码是非常重要的。什么是文件编码?文件编码是一种将字符转换为字节的方......
  • java 添加一个定时任务 可关闭
    Java中的定时任务与可关闭性在开发过程中,经常会遇到需要定时执行某些任务的场景,比如定时发送邮件、定时备份数据库等。Java提供了多种方式来实现定时任务,其中最常用的是使用Timer类和ScheduledExecutorService接口。本文将介绍如何使用这两种方式实现定时任务,并且使其可关闭。使......
  • java 文件上传 文件名乱码
    Java文件上传:文件名乱码的问题在Java开发中,文件上传是一个常见的需求。然而,有时候我们会遇到文件名乱码的问题。这篇文章将介绍文件名乱码的原因,并提供一些解决方案。1.问题描述在Java文件上传过程中,文件名乱码可能会出现在两个地方:浏览器端和服务器端。浏览器端的文件名乱码通......
  • Java学习day07: 小练习
    题目1为二次方程式$ax^2+bx+c=0$设计一个名为QuadraticEquation的类,这个类包括:代表三个系数的私有数据域a、b和c;一个参数为a、b和c的构造方法;数据域a、b和c的三个get/set方法;一个名为getDiscriminant()的方法返回判别式,$b^2-4ac$;一个名为getRoot1()和getRoot2()的......
  • Java使用snmp协议采集服务器信息
    Java使用snmp协议采集服务器信息  一.snmp简介 SNMP是专门设计用于在IP网络管理网络节点(服务器、工作站、路由器、交换机及Hubs等)的一种标准协议,它是一种应用层协议。SNMP使网络管理员能够管理网络效能,发现并解决网络问题以及规划网络增长。通过SNMP接收随机消息(及......
  • java rmi上传下载512字节OutputStream
    /*JADXINFO:Accessmodifierschangedfrom:protected*/publicfinalvoiddownloadFile(Parameterparameter,OutputStreamout)throwsXException{if(!this.session.isEffective()){thrownewXException(10000000,"连接会话无效&......
  • 反射记录
    Java反射是一种机制,可以在运行时检查、调用和实例化类,无需在编译时确定类的名字。使用反射可以动态地获取类的信息,并在运行时操作类的属性、方法和构造函数。反射常用的方法名及作用介绍如下:1.`getClass()`:获取对象的Class对象,即获取对象所属的类的信息。2.`getMethods()`:获取公......
  • [Javascript] [] is ArrayList
    Runthefollowingcode,foundthatfor get&push&pop,itisO(1)time;Butfor shift/unshfit,itisO(n)time.Inthiscases,Javascript's[],isaArrayList,everytimeyoudoshiftorunshiftitneedtomovetherestofitemsbyoneoffw......