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 ...
随机推荐
- [转帖]oracle通过pid查找执行SQL
通过TOP 命令查看PID:1560 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1560 oracle 20 0 38.978g 0. ...
- [转帖]TiDB-unsafe recover(三台tikv宕机两台)
一.背景 名称 数量 tikv 3 副本 3 1.故障: 因为某些原因,两台tikv不可连接,出现region不能访问的故障 2.几条理论: 2.1.多副本原则 存在一半以上的副本则集群访问不受影响( ...
- [转帖]Kafka之ISR机制的理解
Kafka对于producer发来的消息怎么保证可靠性? 每个partition都给配上副本,做数据同步,保证数据不丢失. 副本数据同步策略 和zookeeper不同的是,Kafka选择的是全部完成同 ...
- [转帖]Shell脚本中利用expect实现非交互式
https://developer.aliyun.com/article/885723?spm=a2c6h.24874632.expert-profile.295.7c46cfe9h5DxWK 简介: ...
- WebAssembly入门笔记[1]:与JavaScript的交互
前一阵子利用Balazor开发了一个NuGet站点,对WebAssembly进行了初步的了解,觉得挺有意思.在接下来的一系列文章中,我们将通过实例演示的方式介绍WebAssembly的一些基本概念和编 ...
- 如何在centos7中完全卸载Python3
如何在centos7中完全卸载Python3?根据查到的资料,主要就是卸载,然后删除一些软连接删除干净,逻辑很简单,贴一些具体的操作代码,记录下来 . 卸载Python3的步骤 #卸载python3 ...
- TienChin 活动管理-添加活动页面
后端 ActivityController.java @Resource private IChannelService iChannelService; /** * 获取渠道列表 * * @retu ...
- 【springboot整合druid】java.sql.SQLException: url not set
问题描述 未使用自动装配的机制,实现springboot整合druid时(就是使用druid的jar包,而不是druid-spring-boot-starter)报错 <dependency&g ...
- C++ Qt开发:数据库与TableView多组件联动
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍TableVi ...
- 2.13 PE结构:实现PE代码段加密
代码加密功能的实现原理,首先通过创建一个新的.hack区段,并对该区段进行初始化,接着我们向此区段内写入一段具有动态解密功能的ShellCode汇编指令集,并将程序入口地址修正为ShellCode地址 ...