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利用反射实现运行时方法调用的更多相关文章

  1. java利用反射动态加载方法

    @参考文章 根据特定字符串加载相应的方法,有人用if else,有人用switch.参数少了或情况少了还好,很多方法真要命,不要紧,java反射拯救你 import java.lang.reflect ...

  2. java利用反射调用类的某个方法

    java利用反射机制 可以动态调用某个类的某个方法,在 扩展系统功能或提供对外接口时经常用的到. 代码如下: 打印类Print.java package com.test.reflct; /** * ...

  3. JavaScript 对引擎、运行时、调用堆栈的概述理解

    JavaScript 对引擎.运行时.调用堆栈的概述理解  随着JavaScript越来越流行,越来越多的团队广泛的把JavaScript应用到前端.后台.hybrid 应用.嵌入式等等领域. 这篇文 ...

  4. 介绍下Java内存区域(运行时数据区)

    介绍下Java内存区域(运行时数据区) Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域.JDK 1.8 和之前的版本略有不同. 下图是 JDK 1.8 对JV ...

  5. java利用反射获取类的属性及类型

    java利用反射获取类的属性及类型. import java.lang.reflect.Field; import java.math.BigDecimal; import java.util.Map ...

  6. JavaScript是如何工作的:引擎,运行时和调用堆栈的概述!

    摘要: 理解JS执行原理. 原文:JavaScript是如何工作的:引擎,运行时和调用堆栈的概述! 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 本文是旨在深入研究JavaScrip ...

  7. 利用反射编写私有 Private 方法的单元测试

    利用反射编写私有 Private 方法的单元测试 最近在添加一个新feature时,鉴于要给自己的代码一是增加代码的强壮性,二是增加代码测试的覆盖率.但是遇到了有些方法是 Private 的,但是在调 ...

  8. Java内存管理:Java内存区域 JVM运行时数据区

    转自:https://blog.csdn.net/tjiyu/article/details/53915869 下面我们详细了解Java内存区域:先说明JVM规范定义的JVM运行时分配的数据区有哪些, ...

  9. 【转】Java利用反射机制访问私有化构造器

    Java利用反射机制访问私有化构造器 博客分类: java   我们都知道,当一个类的构造方法被设为私有的时候(private),在其他类中是无法用new来实例化一个对象的. 但是有一种方法可以把带有 ...

  10. 【转】Java Web 项目获取运行时路径 classpath

    Java Web 项目获取运行时路径 classpath 假设资源文件放在maven工程的 src/main/resources 资源文件夹下,源码文件放在 src/main/java/下, 那么ja ...

随机推荐

  1. 浏览器兼容 : IE10

    <script> /*@cc_on @*//*@ if (document.documentMode == 10) { // 只在 IE10 文档模式下运行,例如 IE10 浏览器或 IE ...

  2. [转帖]一文快速入门 ClickHouse

    https://zhuanlan.zhihu.com/p/621480049 什么是clickhouse ClickHouse是一种OLAP类型的列式数据库管理系统,这里有两个概念:OLAP.列式数据 ...

  3. [转帖]【k8s】5、资源管理命令-声明式

    文章目录 一. yaml和json介绍 1.yuml语言介绍 2.k8s支持的文件格式 3.yaml和json的主要区别 二.声明式对象管理 1.命令式对象配置 2.声明式对象配置 3.声明式对象管理 ...

  4. 使用rpmbuild打包erlang和rabbitmq进行部署服务的方法

    使用rpmbuild打包erlang和rabbitmq进行部署服务的方法 背景说明 1. rabbitmq 是基于 erlang 开发的消息列队, 本身rabbitmq 自己不区分架构. 2. 但是e ...

  5. 手把手带你开发starter,点对点带你讲解原理

    京东物流 孔祥东 _____ _ ____ _ / ____| (_) | _ \ | | | (___ _ __ _ __ _ _ __ __ _| |_) | ___ ___ | |_ \___ ...

  6. 【DP】DMOPC '21 Contest 8 P5 - Tree Building

    Problem Link 给定 \(n,m\) 和一个长为 \(m\) 的代价序列,对于一棵 \(n\) 个节点,每个节点度数不超过 \(m\) 的树,定义它的代价为 \(\sum\limits_{i ...

  7. ST 表并查集小记🐤

    ST 表维护并查集,在 $O(n \log n)$ 时间内处理 $[l_1,r_1]$ 内每个点依次向 $[l_2,r_2]$ 中的点连边(共连 $r_1-l_1+1$ 条边) 首先变成对于 $l_1 ...

  8. 设计模式学习-使用go实现责任链模式

    责任链模式 定义 优点 缺点 适用范围 代码实现 责任链模式对比装饰模式 参考 责任链模式 定义 责任链模式(Chain Of Responsibility):使多个对象都有机会处理请求,从而避免请求 ...

  9. 基于volcano实现节点真实负载感知调度

    本文分享自华为云社区<基于volcano实现节点真实负载感知调度>,作者: 可以交个朋友. 背景 默认调度器调度器视某个节点的空闲可调度资源=节点可分配资源 - SUM(节点上已调度Pod ...

  10. LeetCode刷题日记 2020/03/25

    力扣刷题继续! 题目:计算三维形体表面积 题干 在 N * N 的网格上,我们放置一些 1 * 1 * 1  的立方体. 每个值 v = grid[i][j] 表示 v 个正方体叠放在对应单元格 (i ...