Java利用反射实现运行时方法调用
1.介绍
在这篇短文中,我们将快速了解如何在运行时使用Java反射API调用方法。
2.准备工作
来创建一个简单的类:
public class Operations {
public double publicSum(int a, double b) {
return a + b;
}
public static double publicStaticMultiply(float a, long b) {
return a * b;
}
private boolean privateAnd(boolean a, boolean b) {
return a && b;
}
protected int protectedMax(int a, int b) {
return a > b ? a : b;
}
}
3.获取一个方法对象
首先,我们需要得到一个Method对象来反射我们想要调用的方法。Class对象表示在其中定义方法的类型,它提供了两种方法。
3.1 getMethod()
我们可以使用getMethod()查找任何公共方法,无论是静态方法还是在类或其任何超类中定义的实例。
它接收方法名称作为第一个参数,后跟方法参数的类型:
Method sumInstanceMethod
= Operations.class.getMethod("publicSum", int.class, double.class);
Method multiplyStaticMethod
= Operations.class.getMethod(
"publicStaticMultiply", float.class, long.class);
3.2 getDeclaredMethod()
我们可以使用getDeclaredMethod()获取类中定义的任何方法。这包括public、protected、default访问,甚至私有方法,但不包括继承的方法。
它接收与getMethod()相同的参数:
Method andPrivateMethod
= Operations.class.getDeclaredMethod(
"privateAnd", boolean.class, boolean.class);
Method maxProtectedMethod
= Operations.class.getDeclaredMethod("protectedMax", int.class, int.class);
4.调用方法
有了方法实例,我们现在可以调用invoke()来执行其潜在方法并获取返回的对象。
4.1 调用实例方法
要调用实例方法,invoke()的第一个参数必须是反射所调用方法的方法实例:
@Test
public void givenObject_whenInvokePublicMethod_thenCorrect() {
Method sumInstanceMethod
= Operations.class.getMethod("publicSum", int.class, double.class);
Operations operationsInstance = new Operations();
Double result
= (Double) sumInstanceMethod.invoke(operationsInstance, 1, 3);
assertThat(result, equalTo(4.0));
}
4.2 调用静态方法
因为静态方法不需要调用实例,所以我们可以传递null作为第一个参数:
@Test
public void givenObject_whenInvokeStaticMethod_thenCorrect() {
Method multiplyStaticMethod
= Operations.class.getDeclaredMethod(
"publicStaticMultiply", float.class, long.class);
Double result
= (Double) multiplyStaticMethod.invoke(null, 3.5f, 2);
assertThat(result, equalTo(7.0));
}
5.方法的可访问性
默认情况下,并非所有反射的方法都是可访问的。这意味着JVM在调用它们时强制执行访问控制检查。
例如,如果我们尝试在其定义类之外调用私有方法,或从子类或其类的包之外调用受保护的方法,我们将得到IllegalAccessException:
@Test(expected = IllegalAccessException.class)
public void givenObject_whenInvokePrivateMethod_thenFail() {
Method andPrivateMethod
= Operations.class.getDeclaredMethod(
"privateAnd", boolean.class, boolean.class);
Operations operationsInstance = new Operations();
Boolean result
= (Boolean) andPrivateMethod.invoke(operationsInstance, true, false);
assertFalse(result);
}
@Test(expected = IllegalAccessException.class)
public void givenObject_whenInvokeProtectedMethod_thenFail() {
Method maxProtectedMethod
= Operations.class.getDeclaredMethod(
"protectedMax", int.class, int.class);
Operations operationsInstance = new Operations();
Integer result
= (Integer) maxProtectedMethod.invoke(operationsInstance, 2, 4);
assertThat(result, equalTo(4));
}
通过对反射方法对象执行setAccessible(true),JVM将取消访问控制检查,并允许我们在不引发异常的情况下调用该方法:
@Test
public void givenObject_whenInvokePrivateMethod_thenCorrect() {
// ...
andPrivateMethod.setAccessible(true);
// ...
Boolean result
= (Boolean) andPrivateMethod.invoke(operationsInstance, true, false);
assertFalse(result);
}
@Test
public void givenObject_whenInvokeProtectedMethod_thenCorrect() {
// ...
maxProtectedMethod.setAccessible(true);
// ...
Integer result
= (Integer) maxProtectedMethod.invoke(operationsInstance, 2, 4);
assertThat(result, equalTo(4));
}
Java利用反射实现运行时方法调用的更多相关文章
- java利用反射动态加载方法
@参考文章 根据特定字符串加载相应的方法,有人用if else,有人用switch.参数少了或情况少了还好,很多方法真要命,不要紧,java反射拯救你 import java.lang.reflect ...
- java利用反射调用类的某个方法
java利用反射机制 可以动态调用某个类的某个方法,在 扩展系统功能或提供对外接口时经常用的到. 代码如下: 打印类Print.java package com.test.reflct; /** * ...
- JavaScript 对引擎、运行时、调用堆栈的概述理解
JavaScript 对引擎.运行时.调用堆栈的概述理解 随着JavaScript越来越流行,越来越多的团队广泛的把JavaScript应用到前端.后台.hybrid 应用.嵌入式等等领域. 这篇文 ...
- 介绍下Java内存区域(运行时数据区)
介绍下Java内存区域(运行时数据区) Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域.JDK 1.8 和之前的版本略有不同. 下图是 JDK 1.8 对JV ...
- java利用反射获取类的属性及类型
java利用反射获取类的属性及类型. import java.lang.reflect.Field; import java.math.BigDecimal; import java.util.Map ...
- JavaScript是如何工作的:引擎,运行时和调用堆栈的概述!
摘要: 理解JS执行原理. 原文:JavaScript是如何工作的:引擎,运行时和调用堆栈的概述! 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 本文是旨在深入研究JavaScrip ...
- 利用反射编写私有 Private 方法的单元测试
利用反射编写私有 Private 方法的单元测试 最近在添加一个新feature时,鉴于要给自己的代码一是增加代码的强壮性,二是增加代码测试的覆盖率.但是遇到了有些方法是 Private 的,但是在调 ...
- Java内存管理:Java内存区域 JVM运行时数据区
转自:https://blog.csdn.net/tjiyu/article/details/53915869 下面我们详细了解Java内存区域:先说明JVM规范定义的JVM运行时分配的数据区有哪些, ...
- 【转】Java利用反射机制访问私有化构造器
Java利用反射机制访问私有化构造器 博客分类: java 我们都知道,当一个类的构造方法被设为私有的时候(private),在其他类中是无法用new来实例化一个对象的. 但是有一种方法可以把带有 ...
- 【转】Java Web 项目获取运行时路径 classpath
Java Web 项目获取运行时路径 classpath 假设资源文件放在maven工程的 src/main/resources 资源文件夹下,源码文件放在 src/main/java/下, 那么ja ...
随机推荐
- MySQL-多表查询练习
首先创建练习所需要的数据表 储备:建表操作: CREATE TABLE `t_dept` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `deptName` VARC ...
- [转帖]Google SRE 薪水,看看同样作为 SRE 的你相差多少
https://zhuanlan.zhihu.com/p/566098252 SRE 是确保所有生产环境(Infra/Server/DBS 等)一直正常运行的人.每个网络科技公司基本都有这个部门.但是 ...
- 有趣的Shell脚本学习
有趣的Shell脚本学习 倒计时脚本 #!/bin/bash echo 20秒倒计时开始: tput sc # 循环40秒 for count in `seq 0 20` do tput rc tpu ...
- [转帖]strace分析sqlplus登录慢问题
一. 问题分析 有时会遇到sqlplus / as sysdba登录非常慢的问题,由于还没登录,通过数据库等待事件一般看不出来啥,需要用到strace这个分析利器.strace有很多参数,后面会列出, ...
- [转帖]kafka漏洞升级记录,基于SASL JAAS 配置和 SASL 协议,涉及版本3.4以下
攻击者可以使用基于 SASL JAAS 配置和 SASL 协议的任意 Kafka 客户端,在对 Kafka Connect worker 创建或修改连接器时,通过构造特殊的配置,进行 JNDI 注入. ...
- It is currently in use by another Gradle instance
FAILURE: Build failed with an exception. * What went wrong: Could not create service of type TaskHis ...
- easyUI 实现查询条件中时间默认当天,第一次不参与查询,当点击查询时参与
前端查询条件: 初始加载页面时,不进行调用方法,不加载数据.前端页面代码如下: 初始化datagrid代码如下: 当点击查询时,调用后台方法进行查询数据
- navicat连接远程docker中的mysql报错解决
总是报错 填写主机地址有错误,终于找到方法,是因为docker中的mysql没有设置ip地址,navicat不识别,奉上 https://blog.csdn.net/qq_42838723/artic ...
- Git如何拉取指定远程分支
转载来自https://www.jianshu.com/p/856ce249ed78 目的 我们想要获取到代码仓库中分支"a" 中的文件到本地,我了解到有三种方法. 代码仓库 ...
- vscode中文搜索乱码或搜索不到
使用vscode在全局搜索时,代码中的内容无法搜索出来,或者搜索出来是乱码. 经验证:与vscode的语言设置无关,设置为中文或英文都是一样的 后面猜想到会不会与文件自身的编码有关,因为我们项目中的代 ...