拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 用Java调用私有方法

用Java调用私有方法

白鹭 - 2022-11-26 447 0 0

1.概述

虽然在Java中将方法private ,以防止从拥有类的外部调用它们,但出于某些原因,我们可能仍需要调用它们。

为此,我们需要解决Java的访问控制问题。这可以帮助我们到达库的某个角落,或者允许我们测试一些通常应保密的代码。


在这个简短的教程中,我们将研究如何验证方法的功能,而不考虑其可见性。我们将考虑两种不同的方法:Java Reflection API和Spring的ReflectionTestUtils 。

2.可见性超出我们的控制

对于我们的示例,让我们使用对long数组进行LongArrayUtil我们的类有两个indexOf方法:

public static int indexOf(long[] array, long target) { return indexOf(array, target, 0, array.length);

 } private static int indexOf(long[] array, long target, int start, int end) { for (int i = start; i < end; i++) { if (array[i] == target) { return i;

 }

 } return -1;

 }

假设这些方法的可见性无法更改,但是我们要调用私有indexOf方法。

3. Java反射API

3.1。用反思找到方法

虽然编译器阻止我们调用类中不可见的函数,但我们可以通过反射来调用函数。首先,我们需要访问描述我们要调用的函数Method

Method indexOfMethod = LongArrayUtil.class.getDeclaredMethod(  "indexOf", long[].class, long.class, int.class, int.class);

我们必须使用getDeclaredMethod才能访问非私有方法。我们在具有函数的类型(在本例中为LongArrayUtil上调用它,并传入参数的类型以标识正确的方法。

如果该方法不存在,则该函数可能会失败并引发异常。

3.2。允许访问方法

现在,我们需要暂时提高方法的可见性:

indexOfMethod.setAccessible(true);

此更改将持续到JVM停止或accessible属性设置回false.

3.3。反射调用方法

最后,我们Method对像上invoke :

int value = (int) indexOfMethod.invoke(

 LongArrayUtil.class, someLongArray, 2L, 0, someLongArray.length);

现在,我们已经成功访问了私有方法。

invoke的第一个参数是目标对象,其余参数需要匹配我们方法的签名。在这种情况下,我们的方法是static ,目标对LongArrayUtil父类– LongArrayUtil。对于调用实例方法,我们将传递要调用其方法的对象。

我们还应注意, invoke返回Object ,对于void函数,该参数为null ,并且需要转换为正确的类型才能使用它。

4. Spring ReflectionTestUtils

到达类的内部是测试中的常见问题。 Spring的测试库提供了一些捷径,以帮助单元测试达到类。这通常可以解决特定于单元测试的问题,在单元测试中,测试需要访问一个私有字段,Spring可能会在运行时实例化该私有字段。

首先,我们需要在pom.xml中spring-test

<dependency>

 <groupId>org.springframeworkgroupId>

 <artifactId>spring-testartifactId>

 <version>5.3.4version>

 <scope>testscope>

 dependency>

现在,我们可以在ReflectionTestUtils invokeMethod函数,该函数使用与上述相同的算法,从而节省了编写大量代码的时间:

int value = ReflectionTestUtils.invokeMethod(

 LongArrayUtil.class, "indexOf", someLongArray, 1L, 1, someLongArray.length);

由于这是一个测试库,因此我们不希望在测试代码之外使用它。

5.注意事项

使用反射绕过功能可见性会带来一些风险,甚至可能无法实现。我们应该考虑:

  • Java安全管理器是否将在我们的运行时中允许

  • 在没有编译时检查的情况下,我们正在调用的函数在将来是否会继续存在

  • 重构我们自己的代码,使事物更清晰可见

六,结论

在本文中,我们研究了如何使用Java Reflection API和Spring的ReflectionTestUtils访问私有方法。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *