java中反射机制的主要作用

2023-11-09

C++自身并没有提供像Java这样完备的反射机制,只是提供了非常简单的动态类型信息,如type_info和typeid。然而在一些C++的第三方框架类库中提供了类似的功能,如MFC、QT。其中MFC是通过宏的方式实现,
QT是通过自己的预编译实现。在目前的主流开发语言中,也只有C#提供的反射机制可以和Java的相提并论。

1. Java的反射机制主要表现为四点:
1) 在运行中分析类的能力;
2) 在运行中查看对象;
3) 实现数组的操作代码;
4) 利用Method对象,这个对象很像C++中的函数指针。
注:Java的基于反射的应用主要用于一些工具类库的开发,在实际的应用程序开发中应用的场景较少。

2. 获取对象的名称(字符串形式) vs 通过对象的名称(字符串形式)创建对象实例,见如下代码:    
 public static void main(String args[]) {
           //1. 通过对象获取其字符串表示的名称  
           Date d = new Date();
             //or Class<? extends Date> c1 = d.class;
           Class<? extends Date> c1 = d.getClass();  
           String className = c1.getName();             

           //2. 通过字符串形式的名称创建类实例。
          className = "java.util." + className;
       try {
       Class c2 = Class.forName(className);
       //这里用到的newInstance用于创建c2所表示的对象实例,但是必须要求待创建的类实例
       //具有缺省构造函数(无参数),很明显newInstance调用并未传入任何参数用于构造对象。
       Date d2 = (Date)c2.newInstance();
       } catch (ClassNotFoundException e) {
       e.printStackTrace();
       } catch (InstantiationException e) {
       e.printStackTrace();
       } catch (IllegalAccessException e) {
       e.printStackTrace();
       }
       }
如果需要通过调用带有参数的构造函数来创建对象实例,需要使用java.lang.reflect.Constructor对象来完成,见如下代码:   
   public static void main(String args[]) {
           String className = "java.util.Date";

           try {
           Class c2 = Class.forName(className);
           //找到只接受一个long类型参数的构造器
           Constructor cc = c2.getConstructor(long.class);
           long ll = 45L;
           //将该Constructor期望的指定类型(long)的参数实例传入并构造Date对象。
           Date dd = (Date)cc.newInstance(ll);
       System.out.println("Date.toString = " + dd);
       } catch (Exception e) {
       e.printStackTrace();
       }
       }
3. 遍历一个未知类型的所有域、构造方法和域方法,见如下函数原型:
  Field[] getFields(); 返回指定对象域字段数组,主要包含该类及其超类的所有公有(public)域。
  Field[] getDeclaredFields();返回指定对象域字段数组,主要包含该类自身的所有域,包括private等。
  Method[] getMethods(); 返回指定对象域方法数组,主要包含该类及其超类的所有公有(public)域方法。
  Method[] getDeclaredMethods();返回指定对象域方法数组,主要包含该类自身的所有域方法,包括private等。
  Constructor[] getConstructors(); 返回指定对象构造函数数组,主要包含该类所有公有(public)域构造器。
  Constructor[] getDeclaredConstructors();返回指定对象构造函数数组,主要包含该类所有域构造器。
  int getModifiers(); 返回一个用于描述构造器、方法或域的修饰符的整型数值,使用Modifier类中的静态方法可以协助分析这个返回值。
  String getName(); 返回一个用于描述构造器、方法和域名的字符串。
  Class[] getParameterTypes(); 返回一个用于描述参数类型的Class对象数组。
  Class[] getReturnType(); 返回一个用于描述返回值类型的Class对象。
     
4. 通过反射编写泛型数组代码,见如下代码比较:       
static Object[] badArrayGrow(Object[] a) {
           int newLength = a.length * 11 / 10 + 10;

           //该对象数组的在创建时是基于Object的,所以返回后,
           //再装回其他类型数组时将会抛出ClassCastException的异常。

           Object[] newArray = new Object[newLength];

           System.arraycopy(a,0,newArray,0,a.length);

           return newArray;

           }            

       static Object goodArrayGrow(Object a) {//这里的参数务必为Object,而不是Object[]  

       Class c1 = a.getClass();
       if (!c1.isArray())  
       return null;

       //这里用于获取数组成员的类型
       Class componentType = c1.getComponentType();
       //获取数组的长度。
       int length = Array.getLength(a);
       int newLength = length * 11 / 10 + 10;
       //通过数组成员的类型和新的长度值来创建一个和参数类型相同的数组,
       //并增加他的空间,最后再返回。

       Object newArray = Array.newInstance(componentType,newLength);
       System.arraycopy(a,0,newArray,0,length);
       return newArray;
       }

5. 在运行时使用反射的对象或动态调用反射之后的方法。
1) 获取域字段和设置域字段:         <pre name="code" class="java">public void testField() {
           Employee harry = new Employee("Harry Hacker",35000,10);
           Class c1 = harry.getClass();

           Field f = c1.getDeclaredField("name");

          //由于name字段有可能是Employee类的私有域字段,如果直接调用会致使JVM
           //抛出安全异常,为了避免该异常的发生,需要调用下面的语句来得以保证。
           f.setAccessible(true);

           Object v = f.get(harry);
           System.out.println(v);
       }
2) 通过Method的invoke函数动态调用反射后的方法:
 该方式有些类似于C#的委托(delegate)和C++的函数指针。     

 public int add(int param1, int param2) {  
           return param1 + param2;  
           }              
           public static void main(String[] args) throws Exception {  
           Class classType = MyTest.class;  
           Object myTest = classType.newInstance();  
           Method addMethod = classType.getMethod("add",int.class,int.class);

           //如果add为静态方法,这里的第一个参数传null
          Object result = addMethod.invoke(myTest, 100,200);  
          System.out.println(result);  
        }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java中反射机制的主要作用 的相关文章

随机推荐

  • 静态分析工具Cppcheck在Windows上的使用

    之前在https blog csdn net fengbingchun article details 8887843 介绍过Cppcheck 那时还是1 x版本 现在已到2 x版本 这里再总结下 Cppcheck是一个用于C C 代码的静
  • (二叉树)从中序和后序遍历构造树

    题目描述 根据一棵树的中序遍历与后序遍历构造二叉树 注意 你可以假设树中没有重复的元素 例如 给出 中序遍历 inorder 9 3 15 20 7 后序遍历 postorder 9 15 7 20 3 返回如下的二叉树 3 9 20 nu
  • 交换a,b, 不使用中间变量

    第一种方法 a a b b a b a a b printf a d b d n a b 第二种方法 swap69 a b a b printf a d b d n a b void swap69 int a int b int pa in
  • 黑盒测试与白盒测试各自的优缺点

    黑盒测试的优点 1 比较简单 不需要了解程序内部的代码及实现 2 与软件的内部实现无关 3 从用户角度出发 能很容易的知道用户会用到哪些功能 会遇到哪些问题 4 基于软件开发文档 所以也能知道软件实现了文档中的哪些功能 5 在做软件自动化测
  • 使用 husky 进行Git提交前的代码校验和 commit msg检查

    husky 是一个 Git Hooks 工具 借助 husky 我们可以在 git 流程的不同生命周期进行一些自动化操作 本文主要介绍提交前 eslint 校验和提交时 commit 信息的规范校验 什么是 Git Hooks Git Ho
  • c调用python库_c中嵌入的python代码 – 导入python库时出错

    我试图使用嵌入在C程序中的 Python 3 5解释器从C接收图像 并将其用作我训练的张量流模型的输入 首先 我将我的图像转换为numpy数组 然后将其发送到python 这是我的简化代码 工作正常 从 here采用的代码 Python代码
  • web测试,App测试,小程序测试区别

    最近项目真的太忙了 不过 今天无论如何我都要更文章了 谢谢大家的支持 不断努力进步 这篇文章 我就是要梳理一下 web测试 app测试 和小程序的区别 话不多说 上主题 web测试 App测试 小程序测试 一 web测试 1 1 什么是we
  • JS时间戳转换方式

    前言 在js中将时间戳转换为常用的时间格式 有三种主要的方式 1 使用JS中已有的函数 例如getFullYear getMonth 等 将时间戳直接转换成对应的年月 2 创建时间过滤器 在其他的页面中直接调用该过滤器 转换时间戳 3 使用
  • 使用trtexec工具多batch推理tensorrt模型(trt模型)

    文章目录 零 pt转onnx模型 一 onnx转trt模型 二 推理trt模型 零 pt转onnx模型 参考 https github com ultralytics yolov5 用根目录下的export py可以转pt为onnx模型 命
  • Gem5模拟器,详解官网教程的statistics and output(三)

    gem5是一个计算机模拟器 它可以用来模拟不同类型的计算机系统 以帮助计算机科学家和工程师更好地理解和优化计算机系统的性能 gem5提供了许多统计信息和输出功能 可以帮助用户更好地了解模拟的计算机系统的性能情况 gem5的统计信息可以通过访
  • Ubuntu20.04配置ESP32-IDFV5.1环境及Component工程样例

    更新Ubuntu20 04下载源 cd etc apt 更新sources list为如下下载源 并保存 添加阿里源 deb http mirrors aliyun com ubuntu focal main restricted univ
  • 【Mac】mac安装go

    1 安装 安装 brew install go 这里采用界面安装 http c biancheng net view 3994 html 验证 go version base lcc lcc go version go version go
  • QT creator同时打开多个运行窗口(客户端窗口)

    一 最近在做TCP多连接server的问题 但是发现qt不能同时打开多个客户端窗口 解决办法 可以使用windows下的cmd命令窗口 用命令的方式运行多个客户端 我的客户端的名字是wbclient exe step1 首先通过cmd进入到
  • tomcat 开放远程调试端口

    1 开启远程调试端口 WIN系统 在catalina bat里 SET CATALINA OPTS server Xdebug Xnoagent Djava compiler NONE Xrunjdwp transport dt socke
  • perl脚本的简单调试方法

    初学perl语言 最先接触的不是它的语法 而是它的调试方法 当时是由于一个perl script生成的html页面无法正常显示 让我找出问题的原因 然后修复 当时是第一次接触perl 完全没有任何了解 就凭着学了几句在Teriminal中可
  • rtt下的adbd使用

    RTT 下的ADBD使用 1 引言 调试柿饼时 需要文件传输 由于智龙平台的RTT环境下USB还没有调试好 这里就使用ADB进行文件传输 找到了何元杰的帖子 并参考 rdb 建立 RTT与PC 的文件传输通道 2 使用环境 2 1 硬件平台
  • 5万条药品数据库下载数据,带图片

    链接 https pan baidu com s 1zBytf7BGty I3FCBPF2PxA 提取码 fshp
  • C#,入门教程(02)—— Visual Studio 2022开发环境搭建图文教程

    如果这是您阅读的本专栏的第一篇博文 建议先阅读如何安装Visual Studio 2022 C 入门教程 01 Visual Studio 2022 免费安装的详细图文与动画教程https blog csdn net beijinghorn
  • 富爸爸穷爸爸

    有意思的观点 1 贫穷和破产的区别 破产是暂时的 而贫穷是永久的 2 我们听说过穷人买彩票中奖的故事 他们一下子暴富起来 但不久又变穷了 还有关于职业运动员的故事 有一个运动员在24岁的时候 一年就挣了几百万美元 但到了34岁的时候却露宿桥
  • java中反射机制的主要作用

    C 自身并没有提供像Java这样完备的反射机制 只是提供了非常简单的动态类型信息 如type info和typeid 然而在一些C 的第三方框架类库中提供了类似的功能 如MFC QT 其中MFC是通过宏的方式实现 QT是通过自己的预编译实现