Java反射机制与Method的invoke方法实现

2023-10-26

一、什么是反射:

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

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

二、反射的原理:

下图是类的正常加载过程、反射原理与class对象:

Class对象的由来是将.class文件读入内存,并为之创建一个Class对象。

三、反射的用途:

1、反编译:.class-->.java

2、通过反射机制访问java对象的属性,方法,构造方法等

3、当我们在使用IDE,比如Ecplise时,当我们输入一个对象或者类,并想调用他的属性和方法是,一按点号,编译器就会自动列出他的属性或者方法,这里就是用到反射。

4、反射最重要的用途就是开发各种通用框架。比如很多框架(Spring)都是配置化的(比如通过XML文件配置Bean),为了保证框架的通用性,他们可能需要根据配置文件加载不同的类或者对象,调用不同的方法,这个时候就必须使用到反射了,运行时动态加载需要的加载的对象。

5、例如,在使用Strut2框架的开发过程中,我们一般会在struts.xml里去配置Action,比如

    <action name="login" class="org.ScZyhSoft.test.action.SimpleLoginAction" method="execute">   
        <result>/shop/shop-index.jsp</result>           
        <result name="error">login.jsp</result>       
    </action>

比如我们请求login.action时,那么StrutsPrepareAndExecuteFilter就会去解析struts.xml文件,从action中查找出name为login的Action,并根据class属性创建SimpleLoginAction实例,并用Invoke方法来调用execute方法,这个过程离不开反射。配置文件与Action建立了一种映射关系,当View层发出请求时,请求会被StrutsPrepareAndExecuteFilter拦截,然后StrutsPrepareAndExecuteFilter会去动态地创建Action实例。

比如,加载数据库驱动的,用到的也是反射。

Class.forName("com.mysql.jdbc.Driver"); // 动态加载mysql驱动

四、反射机制常用的类:

Java.lang.Class;

Java.lang.reflect.Constructor;

Java.lang.reflect.Field;

Java.lang.reflect.Method;

Java.lang.reflect.Modifier;

五、反射的基本使用:

1、获得Class对象:主要有三种方法:

(1)Object-->getClass

(2)任何数据类型(包括基本的数据类型)都有一个“静态”的class属性

(3)通过class类的静态方法:forName(String className)(最常用)

package fanshe;
 
public class Fanshe {
	public static void main(String[] args) {
		//第一种方式获取Class对象  
		Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
		Class stuClass = stu1.getClass();//获取Class对象
		System.out.println(stuClass.getName());
		
		//第二种方式获取Class对象
		Class stuClass2 = Student.class;
		System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
		
		//第三种方式获取Class对象
		try {
			Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
			System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
	}
}

注意,在运行期间,一个类,只有一个Class对象产生,所以打印结果都是true;

三种方式中,常用第三种,第一种对象都有了还要反射干什么,第二种需要导入类包,依赖太强,不导包就抛编译错误。一般都使用第三种,一个字符串可以传入也可以写在配置文件中等多种方法。

2.通过反射来生成对象 

主要有两种方式

(1)使用Class对象的newInstance()方法来创建Class对象对应类的实例。

    Class<?> c = String.class;
    Object str = c.newInstance();

(2)先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建对象,这种方法可以用指定的构造器构造类的实例。

//获取String的Class对象
Class<?> c = String.class;
//通过Class对象获取指定的Constructor构造器对象
Constructor constructor=c.getConstructor(String.class);
//根据构造器创建实例:
Object obj = constructor.newInstance(“hello reflection”);

3.获取成员方法并调用:

由创建的Class对象调用该方法,返回一个Method的对象或对象数组。  

1.批量的:
          public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
          public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
  2.获取单个的:
          public Method getMethod(String name,Class<?>... parameterTypes):
                     参数:
                          name : 方法名;
                          Class ... : 形参的Class类型对象
          public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
 
       



Method对象调用方法:
          Method --> public Object invoke(Object obj,Object... args):
                      参数说明:
                      obj : 要调用方法的对象;
                     args:调用方式时所传递的实参

六、Method的invoke方法 

给出invoke方法多态特性的演示代码:

public class MethodInvoke {
 
	public static void main(String[] args) throws Exception {
		Method animalMethod = Animal.class.getDeclaredMethod("print");
		Method catMethod = Cat.class.getDeclaredMethod("print");
		
		Animal animal = new Animal();
		Cat cat = new Cat();
		animalMethod.invoke(cat);
		animalMethod.invoke(animal);
		
		catMethod.invoke(cat);
		catMethod.invoke(animal);
	}
	
}
 
class Animal {
	
	public void print() {
		System.out.println("Animal.print()");
	}
	
}
 
class Cat extends Animal {
	
	@Override
	public void print() {
		System.out.println("Cat.print()");
	}
	
}

代码中,Cat类覆盖了父类Animal的print()方法, 然后通过反射分别获取print()的Method对象。最后分别用Cat和Animal的实例对象去执行print()方法。其中animalMethod.invoke(animal)和catMethod.invoke(cat),示例对象的真实类型和Method的声明Classs是相同的,按照预期打印结果;animalMethod.invoke(cat)中,由于Cat是Animal的子类,按照多态的特性,子类调用父类的的方法,方法执行时会动态链接到子类的实现方法上。因此,这里会调用Cat.print()方法;而catMethod.invoke(animal)中,传入的参数类型Animal是父类,却期望调用子类Cat的方法,因此这一次会抛出异常。代码打印结果为:

Cat.print()
Animal.print()
Cat.print()
Exception in thread "main" java.lang.IllegalArgumentException: object is not an instance of declaring class
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.wy.invoke.MethodInvoke.main(MethodInvoke.java:17)
 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java反射机制与Method的invoke方法实现 的相关文章

  • Java中String的字符编码是什么?

    我实际上对 Java 中字符串的编码感到困惑 我有一些问题 如果您知道答案 请帮助我 1 Java字符串在内存中的本机编码是什么 当我写作时String a Hello 将以哪种格式存储 由于 Java 是独立于机器的 我认为系统不会进行编
  • 如果我在 XML 布局中声明一个片段,如何将它传递为 Bundle?

    我有一个活动已替换为片段 该活动采用了一个 Intent 其中包含一些有关该活动应该显示哪些数据的额外信息 现在 我的 Activity 只是执行相同工作的 Fragment 的包装器 如果我使用标记在 XML 中声明该片段 如何将该捆绑包
  • 正则表达式奇/偶数

    我有一个正则表达式问题 我不知道该怎么做 它必须匹配开头包含任意数量的 a 的所有字符串 如果 a 的数量为偶数 则匹配单个 0 如果 a 的数量为奇数 则匹配单个 1 如何跟踪偶数 奇数 Sample aaa1 aaaa0 a aa 1
  • 如何生成带logo的二维码?

    我正在为 Android 设备开发应用程序 我想生成带有徽标的二维码 With ZXing I know how to generate simple QR codes like this one But I want to generat
  • 查看登录设备

    我想查看Log在设备上 即System out println 我可以查看DDMS但如何在运行时在设备屏幕上查看APK文件 还有一个适用于 Android 的 Logcat 应用程序 code google com p android ra
  • 如何在 Jboss 7.1 中配置简单身份验证

    我正在从事由以下人员编写的项目纯jsps 脚本 不使用任何框架 jboss版本 jboss as 7 1 0 Final 我现在正在尝试在其上添加简单的身份验证 因此 当用户尝试浏览 jsp 时 比如说 http localhost myC
  • Java 中修剪字符串的可能前缀

    I have String str 我想从中提取不包括可能的前缀的子字符串 abc 我想到的第一个解决方案是 if str startsWith abc return str substring abc length return str
  • 为什么要分离接口和实现?

    在生产代码中 我经常看到定义如下的类 public interface SomeComponent Some methods public class SomeComponentImpl implements SomeComponent S
  • 我的代码中出现 ArrayIndexOutOfBoundsException 的原因是什么?

    我正在 Java 中实现凸包的格雷厄姆扫描算法 我在运行代码时收到此错误 对于输入字符串 10 18 Exception in thread main java lang ArrayIndexOutOfBoundsException 0 a
  • 我收到异常: java.lang.IllegalStateException: getOutputStream() 已被调用用于此响应

    我想编写代码来下载保留在我的系统中的文件 这是我的代码 在控制器类中 我有以下映射 RequestMapping value processFile method RequestMethod POST public ResponseBody
  • Checkstyle 规则防止调用某些方法和构造函数

    是否可以使用 Checkstyle 来禁止使用某些使用系统相关默认值 区域设置 字符集等 的构造函数或方法 我更喜欢强制执行一项政策 程序员应该明确了解系统相关的值 所以我认为以下物品是危险的 all the constructors of
  • 更改单击后退按钮上的 BottomNavigationView 图标

    在我的布局的底部有一个底部导航视图与三个片段 如果我单击后退按钮 片段将切换 但底部图标不会切换 我该如何修复它 addToBackStack 有效 也许您有一些关于美化代码的建议 在活动或片段中添加片段标签是一个好的做法吗 public
  • 导入数据期间解析日期格式的最佳方法

    我创建了在数据导入 400 K 记录 期间解析视图不同日期格式的方法 我的方法捕获 ParseException 并尝试在不同时使用下一种格式解析日期 问题 在数据导入期间设置正确的日期格式是更好的方法 更快 吗 private stati
  • Java中的字符算术

    在玩的过程中 我遇到了一些对我来说似乎很奇怪的事情 以下不是有效的 Java 代码 char x A x x 1 possible loss of precision 因为其中一个操作数是整数 所以另一个操作数被转换为整数 结果无法分配给字
  • 需要在 java api 中的 Solr 搜索中搜索文本及其周围的几行

    我正在使用 solr 7 7 2 并且我使用 solrj 在 Solr 中编写了一个 Java 程序 该程序在一个巨大的文本文件中搜索单词 我使用以下代码来显示代表整个文本的搜索结果 SolrQuery params new SolrQue
  • 如何将 Java 字节数组转换为 Scala 字节数组?

    我是 Scala 新手 目前正在从事一个涉及 Java 和 Scala 模块的项目 现在我想使用 byte 类型的参数从 Java 调用 Scala 方法 Scala 方法的签名为 def foo data Array Byte Java
  • 策略模式的现实示例

    我一直在读关于OCP原理 http en wikipedia org wiki Open closed principle以及如何使用策略模式来实现这一目标 我打算尝试向几个人解释这一点 但我能想到的唯一例子是根据 订单 的状态使用不同的验
  • Spring Boot MultipartFile上传getOriginalFileName根据浏览器不同而不同

    我使用的是 spring boot 1 5 7 RELEASE 版本 我使用以下方法上传文件 Autowired private MyService mySerice RequestMapping value uploadFile meth
  • Activity 在 Android 上创建两次

    首先 我是 Android 开发新手 所以请耐心等待 我将从用户界面开始 我有一个按钮 一旦您点击它 就会启动一个活动以获取结果 public class GUIActivity extends Activity Override publ
  • 使用 jar 外部的配置启动 .jar,但能够从任何当前目录执行此操作

    我一直在努力解决一个特定的问题 我在 jar 文件中有一个 Java 程序 并且在 jar 之外有一个 lib 目录和一个 config 目录 但与 jar 本身所在的目录位于同一目录中 我正在尝试参考config foo config从代

随机推荐

  • 2023年第14届蓝桥杯题解

    这里写目录标题 日期统计 01 串的熵 冶炼金属 飞机降落 接龙数列 子串简写 日期统计 小蓝现在有一个长度为 100 的数组 数组中的每个元素的值都在 0 到 9 的范围之内 数组中的元素从左至右如下所示 5 6 8 6 9 1 6 1
  • es报错:Exception in thread “main“ SettingsException[Failed to load settings from [elasticsearch.yml]]

    配置参数空格问题 Failed to load settings from 小小的 我 2017 10 12 17 41 00 3068 收藏 版权 Exception in thread main SettingsException Fa
  • centos7.4 docker容器连不上宿主机mysql

    docker容器连不上宿主机mysql 文章目录 docker容器连不上宿主机mysql 一 docker和宿主机网络 1 在docker容器里localhost并不是指宿主机的localhost 2 在docker运行时就和宿主机建立了虚
  • 信息存储服务器机房有辐射吗,服务器机房有辐射大吗

    弹性云服务器 ECS 弹性云服务器 Elastic Cloud Server 是一种可随时自助获取 可弹性伸缩的云服务器 帮助用户打造可靠 安全 灵活 高效的应用环境 确保服务持久稳定运行 提升运维效率 三年低至5折 多种配置可选了解详情
  • arm嵌入式led灯闪烁实验报告_led闪烁实验报告.doc

    led闪烁实验报告 篇一 单片机实验 LED灯闪烁实验 实 验 报 告 课程名称 实验项目 2016年 3 月 13 日 实验目的 1 掌握51单片机开发板的使用步骤 2 掌握51单片机开发板所需软件的安装过程 3 以LED灯闪烁为例子 掌
  • express:webpack dev-server中如何将对后端的http请求转到https的后端服务器中?

    在上一篇文章 Webpack系列 在Webpack Vue开发中如何调用tomcat的后端服务器的接口 我们介绍了如何将对于webpack dev server的数据请求转发到后端服务器上 这在大部分情况下就够用了 然后现在问题又来了 在生
  • qt中ui的 使用介绍

    1 什么是ui ui通常是用Qt 设计师设计出来的界面文件的后缀 通常情况下ui是一个指向这个界面类的指针 ui gt 一般就是用来访问这个界面类里面的控件 例如你的ui文件里有一个叫okButton的QPushButton 你就可以这样来
  • Apache Hook机制解析(下)——实战:在自己的代码中使用Apache的钩子

    在前文 Apache Hook机制解析 上 钩子机制的实现 和 Apache Hook机制解析 中 细节讨论 的基础上 我们对Apache的钩子机制已经有了较多的了解 下面的代码实战演示了一个日志钩子的声明 定义和使用 在VC6 0上编译测
  • MMClassification(一)

    1 介绍 一句话总结 基于pytorch的强大模块化组件式的分类框架 相关资料 中文文档 GitHub 课程学习 深入学习直接使用官方文档学习效果最好 本文记录学习过程知识以便快速回顾和查找 其中包含个人的学习总结 仅做参考 2 项目结构
  • 刷脸支付还可以带来新的互动体验和应用

    支付宝领先的微信支付是依附于电商的绝对优势 微信支付凭借其10亿用户的优势 正在与支付宝抗衡 近几年来 移动支付的快速发展带动了支付技术的变革 nfc支付 二维码支付 指纹支付等支付方式活跃在我们的日常生活中 随着人脸识别技术的成熟和人们对
  • 三菱FX3U——ST编程红绿灯

    一个循环周期是32秒 南北向绿灯和东西向红灯亮10秒后 两侧黄灯亮3秒 黄灯在闪烁3秒 南北向红灯和东西向绿灯亮10秒 两侧黄灯亮3秒 黄灯在闪烁3秒 添加启动和停止 按下启动按钮 使定时器复位 通过置位M0 让标签的状态赋值给输出点 通过
  • DataGrip的简单使用笔记

    目录 导入数据 关键字导航 全局搜索 结果集搜索 导航到关联数据 结果集数据过滤 行转列 变量重命名 自动检测无法解析的对象 权限定字段名 通配符自动展开 大写自动转换 sql格式化 多光标模式 代码注释 列编辑 https pan bai
  • rk3399 高可靠OTA升级

    https blog csdn net m0 37631324 article details 106254910
  • auto_deleter 使用,定义自动销毁对象

    template
  • Windows中安装ElasticSearch(单机+集群+Kibana)

    系统版本 Windows 10 ElasticSearch版本 7 15 2 https artifacts elastic co downloads elasticsearch elasticsearch 7 15 2 windows x
  • linux 网卡驱动升级,安装或更新CentOS平台的网卡驱动程序

    基于Linux平台安装或更新网卡驱动程序与Windows平台相差不大 首先查阅出主机网卡的具体型号 Windows平台可以借助鲁大师等硬件检测工具查看网卡 Linux平台有适用的命令lspci ethtool查看 在CentOS6 7平台下
  • 【欧拉openEuler 】 ssh安装、配置和远程控制

    1 查看SSH是否安装 一般是默认安装好了的 changairjb localhost rpm qa grep ssh libssh 0 9 5 1 oe1 aarch64 openssh 8 2p1 13 oe1 aarch64 open
  • 01-初识HTML

    01 初识HTML 学习目标 理解HTML的基本语法 掌握排版标签实现标题等效果 相对路径和绝对路径 媒体标签 图片 音频 视频 超链接 一 基础认知 了解网页组成和五大浏览器 明确Web标准的构成 1 1 认识网页 以下网页有哪些部分组成
  • (C语言)16进制转10进制

    include
  • Java反射机制与Method的invoke方法实现

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