Call private methods java

Вызов частного метода на Java

В то время как методы частные в Java, чтобы предотвратить их вызов из-за пределов класса владение, мы, возможно, все еще придется вызвать их по некоторым причинам.

Для этого нам необходимо обойти элементы управления доступом Java. Это может помочь нам добраться до угла библиотеки или позволить нам протестировать код, который обычно должен оставаться закрытым.

В этом коротком учебнике мы посмотрим, как мы можем проверить функциональность метода, независимо от его видимости. Рассмотрим два разных подхода: API Отражения Java и Spring’s ReflectionTestUtils.

2. Видимость вне нашего контроля

Для нашего примера давайте использовать утилиту класса ЛонгАррайУтил который работает на долго Массивы. Наш класс имеет два 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 indexOfMethod = LongArrayUtil.class.getDeclaredMethod( "indexOf", long[].class, long.class, int.class, int.class);

Мы должны использовать getDeclaredMethod для доступа к не частным методам. Мы называем это по типу, который имеет функцию, в данном случае, ЛонгАррайУтил , и мы проходим в типах параметров, чтобы определить правильный метод.

Читайте также:  Textcontent javascript что это

Функция может выйти из строя и сделать исключение, если метода не существует.

3.2. Разрешить доступ к методу

Теперь нам нужно временно повысить видимость метода:

indexOfMethod.setAccessible(true);

Это изменение будет продолжаться до тех пор, пока JVM не остановится, или доступные свойство возвращается к ложный.

3.3. Вызов метода с отражением

Наконец, мы называем вызов на объекте Метода:

int value = (int) indexOfMethod.invoke( LongArrayUtil.class, someLongArray, 2L, 0, someLongArray.length);

Теперь мы успешно получили доступ к частному методу.

Первый аргумент в вызвать является целевым объектом, а остальные аргументы должны соответствовать подписи нашего метода. Как и в данном случае, наш метод статические , и целевым объектом является родительский класс – ЛонгАррайУтил . Для вызова методов экземпляра мы передавайте объект, метод которого мы называем.

Следует также отметить, что вызвать возвращает Объект , который является нулевой для недействительными функций, и который нуждается в литье в правильный тип для того, чтобы использовать его.

4. Весенний рефлексТестУтилы

Достижение внутренних классов является общей проблемой в тестировании. Тестовая библиотека Spring предоставляет несколько ярлыков, которые помогут унитарным тестам достичь классов. Это часто решает проблемы, характерные для унитарных тестов, где тест должен получить доступ к частному полю, которое Spring может мгновенно использовать во время выполнения.

Во-первых, мы должны добавить весенне-тестовый зависимости в нашем pom.xml:

 org.springframework spring-test 5.3.4 test 

Теперь мы можем использовать вызватьМетход функции в ОтражениеТестУтилы , который использует тот же алгоритм, как выше, и экономит нам писать столько кода:

int value = ReflectionTestUtils.invokeMethod( LongArrayUtil.class, "indexOf", someLongArray, 1L, 1, someLongArray.length);

Поскольку это тестовая библиотека, мы не ожидаем использовать ее за пределами тестового кода.

5. Соображения

Использование отражения для обхода видимости функции имеет некоторые риски и может быть даже невозможно. Мы должны рассмотреть:

  • Позволит ли менеджер безопасности Java это в нашем времени выполнения
  • Будет ли функция, которую мы вызываем, без проверки времени компиляции, будет продолжать существовать для нас, чтобы позвонить в будущем
  • Рефакторинг нашего собственного кода, чтобы сделать вещи более заметными и доступными

6. Заключение

В этой статье мы рассмотрели, как получить доступ к частным методам с помощью API Java Reflection и использовать данные ОтражениеТестУтилы .

Как всегда, пример кода для этой статьи можно найти более на GitHub .

Читайте ещё по теме:

Источник

Call private methods java

Although methods are used in Java private to prevent them from being called from outside the owning class, for some reasons, we may still need to call them.

To this end, we need to solve the Java access control problem. This can help us get to a corner of the library, or allow us to test some code that should normally be kept secret.

In this short tutorial, we will examine how to verify the functionality of the method, regardless of its visibility. We will consider two different methods: Java Reflection API and Spring ReflectionTestUtils .

2.Visibility is beyond our control

For our example, let’s use our class on the long array to LongArrayUtil have two indexOf methods:

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;
>

Suppose the visibility of these methods cannot be changed, but we want to call private indexOf methods.

3.Java Reflection API

3.1. Find a way with reflection

Although the compiler prevents us from calling functions that are not visible in the class, we can call functions through reflection. First, we need access to describe the function we want to call Method

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

We must use getDeclaredMethod to access non-private methods. We LongArrayUtil call it on the type that has a function (in this case, it is) and pass in the type of the parameter to identify the correct method.

If the method does not exist, the function may fail and raise an exception.

3.2. Allow access method

Now, we need to temporarily increase the visibility of the method:

indexOfMethod.setAccessible(true);

This change will continue until the JVM is stopped or the accessible property is set back false.

3.3. Reflection call method

Finally, we Method are on the subject invoke :

int value = (int) indexOfMethod.invoke( 
LongArrayUtil.class, someLongArray, 2L, 0, someLongArray.length);

Now, we have successfully accessed the private method.

invoke The first parameter of is the target object, and the remaining parameters need to match the signature of our method. In this case, our approach is static to target the LongArrayUtil parent class-LongArrayUtil. For calling an instance method, we will pass the object whose method is to be called.

We should also note that invoke return Object , for void functions, the parameter is null , and need to be converted to the correct type to use it.

4.Spring ReflectionTestUtils

Reaching the inside of the class is a common problem in testing. Spring’s test library provides some shortcuts to help unit tests reach classes. This can usually solve problems specific to unit tests.In unit tests, the test needs to access a private field, and Spring may instantiate the private field at runtime.

First, we need to write in pom.xml spring-test

 
org.springframework
spring-test
5.3.4
test

Now, we can ReflectionTestUtils invokeMethod use the same algorithm as above in the function, which saves the time of writing a lot of code:

int value = ReflectionTestUtils.invokeMethod( 
LongArrayUtil.class, "indexOf", someLongArray, 1L, 1, someLongArray.length);

Since this is a test library, we don’t want to use it outside of the test code.

5.Matters needing attention

Using reflection to bypass functional visibility brings some risks and may not even be possible. We should consider:

  • Will the Java Security Manager be allowed in our runtime
  • Without compile-time checking, whether the function we are calling will continue to exist in the future
  • Refactor our own code to make things more visible

Six, conclusion

In this article, we studied how to use Java Reflection API and Spring to ReflectionTestUtils access private methods.

Источник

Java Reflection — Private Fields and Methods

Despite the common belief it is actually possible to access private fields and methods of other classes via Java Reflection. It is not even that difficult. This can be very handy during unit testing. This text will show you how.

Note: This only works when running the code as a standalone Java application, like you do with unit tests and regular applications. If you try to do this inside a Java Applet, you will need to fiddle around with the SecurityManager. But, since that is not something you need to do very often, it is left out of this text so far.

Note: There has been a lot of talk about disabling the ability to access private fields via reflection from Java 9. From my experiments it seems to still be possible in Java 9, but be aware that this might change in a future Java version.

Accessing Private Fields

To access a private field you will need to call the Class.getDeclaredField(String name) or Class.getDeclaredFields() method. The methods Class.getField(String name) and Class.getFields() methods only return public fields, so they won’t work. Here is a simple example of a class with a private field, and below that the code to access that field via Java Reflection:

public class PrivateObject < private String privateString = null; public PrivateObject(String privateString) < this.privateString = privateString; >>
PrivateObject privateObject = new PrivateObject("The Private Value"); Field privateStringField = PrivateObject.class. getDeclaredField("privateString"); privateStringField.setAccessible(true); String fieldValue = (String) privateStringField.get(privateObject); System.out.println("fieldValue fieldValue = The Private Value", which is the value of the private field privateString of the PrivateObject instance created at the beginning of the code sample.

Notice the use of the method PrivateObject.class.getDeclaredField("privateString"). It is this method call that returns the private field. This method only returns fields declared in that particular class, not fields declared in any superclasses.

Notice the line in bold too. By calling Field.setAcessible(true) you turn off the access checks for this particular Field instance, for reflection only. Now you can access it even if it is private, protected or package scope, even if the caller is not part of those scopes. You still can't access the field using normal code. The compiler won't allow it.

Accessing Private Methods

To access a private method you will need to call the Class.getDeclaredMethod(String name, Class[] parameterTypes) or Class.getDeclaredMethods() method. The methods Class.getMethod(String name, Class[] parameterTypes) and Class.getMethods() methods only return public methods, so they won't work. Here is a simple example of a class with a private method, and below that the code to access that method via Java Reflection:

public class PrivateObject < private String privateString = null; public PrivateObject(String privateString) < this.privateString = privateString; >private String getPrivateString() < return this.privateString; >>

PrivateObject privateObject = new PrivateObject("The Private Value"); Method privateStringMethod = PrivateObject.class. getDeclaredMethod("getPrivateString", null); privateStringMethod.setAccessible(true); String returnValue = (String) privateStringMethod.invoke(privateObject, null); System.out.println("returnValue returnValue = The Private Value", which is the value returned by the method getPrivateString() when invoked on the PrivateObject instance created at the beginning of the code sample.

Notice the use of the method PrivateObject.class.getDeclaredMethod("privateString") . It is this method call that returns the private method. This method only returns methods declared in that particular class, not methods declared in any superclasses.

Notice the line in bold too. By calling Method.setAcessible(true) you turn off the access checks for this particular Method instance, for reflection only. Now you can access it even if it is private, protected or package scope, even if the caller is not part of those scopes. You still can't access the method using normal code. The compiler won't allow it.

Источник

Оцените статью