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 ...
随机推荐
- c# 编写 WebAssembly
创建一个.net 7.0类库工程,引用下面的nuget包: <PackageReference Include="Microsoft.AspNetCore.Components.Web ...
- ONVIF网络摄像头(IPC)客户端开发—RTSP RTCP RTP加载H264视频流
前言: RTSP,RTCP,RTP一般是一起使用,在FFmpeg和live555这些库中,它们为了更好的适用性,所以实现起来非常复杂,直接查看FFmpeg和Live555源代码来熟悉这些协议非常吃力, ...
- [转帖]Debian开启SSH
一.Debian开启SSH 参考链接: https://blog.csdn.net/zzpzheng/article/details/71170572 https://help.aliyun.com/ ...
- [转帖]Linux系统NVME盘分区和挂载
https://www.jianshu.com/p/04327f1b97cb 查看系统里面识别到的硬盘和分区的信息 $ sudo fdisk -l Disk /dev/nvme1n1: 1.8 TiB ...
- [转帖]编译安装goofys挂载Scaleway免费75G对象存储
日常•2022年5月29日 goofys编译 goofys是一个开源的使用Go编写的s3存储桶挂载工具,主打高性能.由于使用Go编写,没有用到什么特别的依赖,自己编译也很容易.截止2022.5.2 ...
- [转帖]Skywalking学习及整合springboot
目录 1. Skywalking概述 2. Skywalking主要功能 3. Skywalking主要特性 4. Skywalking架构简介 5. Spring Cloud与Skywalking实 ...
- Linux下面sysstat的安装与简介
https://blog.51cto.com/smoke520/2160073 在Linux系统下获取sysstat-10.0.5.tar.gz的两种方式: 方式一: 下载sysstat-10.0 ...
- 冷备份MySQL数据库并且使用Docker直接运行的操作过程
备份数据库 查看数据库的数据文件的位置 systemctl status mysqld 查看启动进程以及防水 /etc/my.conf 查看datadir 指向Mysql数据库的存储数据路径. 关闭数 ...
- axios文件上传和 Content-Type类型介绍
Content-Type的作用是什么? Content-Type: 用于在请求头部指定资源的类型和字符编码. 请求头中的content-type,就是 B端发给S端的数据类型描述 . 即告诉服务器端, ...
- echarts给每个柱状图配置不同的颜色
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...