개인 메소드를 호출하는 방법이 있습니까?
XML과 리플렉션을 사용하여을 Object
다른 클래스 로 반환 하는 클래스가 있습니다.
일반적으로 이러한 객체는 외부 객체의 하위 필드이지만 때로는 생성하려는 객체입니다. 나는 이와 같은 것을 시도했지만 아무 소용이 없습니다. Java가 private
리플렉션을위한 메소드에 액세스 할 수 없기 때문이라고 생각합니다 .
Element node = outerNode.item(0);
String methodName = node.getAttribute("method");
String objectName = node.getAttribute("object");
if ("SomeObject".equals(objectName))
object = someObject;
else
object = this;
method = object.getClass().getMethod(methodName, (Class[]) null);
제공된 방법이 private
이면로 실패합니다 NoSuchMethodException
. 메소드 public
를 만들거나 다른 클래스를 만들어서 해결할 수 있습니다.
간단히 말해, 나는 private
반사를 통해 방법에 액세스 할 수있는 방법 이 있는지 궁금했습니다 .
리플렉션을 사용하여 개인 메서드를 호출 할 수 있습니다. 게시 된 코드의 마지막 비트 수정 :
Method method = object.getClass().getDeclaredMethod(methodName);
method.setAccessible(true);
Object r = method.invoke(object);
몇 가지 경고가 있습니다. 먼저, getDeclaredMethod
현재에 선언 된 메소드 만 찾고 Class
슈퍼 타입에서 상속되지 않습니다. 따라서 필요한 경우 구체적 클래스 계층 구조를 탐색하십시오. 둘째, 방법의 SecurityManager
사용을 막을 수 있습니다 setAccessible
. 따라서 PrivilegedAction
( AccessController
또는 사용 Subject
) 으로 실행해야 할 수도 있습니다 .
사용 getDeclaredMethod()
후 개인 Method 객체를 얻을 수있는 사용 method.setAccessible()
실제로 호출 할 수 있도록.
메소드가 기본이 아닌 데이터 유형을 승인하면 다음 메소드를 사용하여 모든 클래스의 개인용 메소드를 호출 할 수 있습니다.
public static Object genericInvokeMethod(Object obj, String methodName,
Object... params) {
int paramCount = params.length;
Method method;
Object requiredObj = null;
Class<?>[] classArray = new Class<?>[paramCount];
for (int i = 0; i < paramCount; i++) {
classArray[i] = params[i].getClass();
}
try {
method = obj.getClass().getDeclaredMethod(methodName, classArray);
method.setAccessible(true);
requiredObj = method.invoke(obj, params);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return requiredObj;
}
허용되는 매개 변수는 obj, methodName 및 매개 변수입니다. 예를 들어
public class Test {
private String concatString(String a, String b) {
return (a+b);
}
}
concatString 메소드는 다음과 같이 호출 할 수 있습니다.
Test t = new Test();
String str = (String) genericInvokeMethod(t, "concatString", "Hello", "Mr.x");
Spring의 ReflectionTestUtils ( org.springframework.test.util.ReflectionTestUtils )를 사용 하여이 작업을 수행 할 수 있습니다
ReflectionTestUtils.invokeMethod(instantiatedObject,"methodName",argument);
Example : if you have a class with a private method square(int x)
Calculator calculator = new Calculator();
ReflectionTestUtils.invokeMethod(calculator,"square",10);
Let me provide complete code for execution protected methods via reflection. It supports any types of params including generics, autoboxed params and null values
@SuppressWarnings("unchecked")
public static <T> T executeSuperMethod(Object instance, String methodName, Object... params) throws Exception {
return executeMethod(instance.getClass().getSuperclass(), instance, methodName, params);
}
public static <T> T executeMethod(Object instance, String methodName, Object... params) throws Exception {
return executeMethod(instance.getClass(), instance, methodName, params);
}
@SuppressWarnings("unchecked")
public static <T> T executeMethod(Class clazz, Object instance, String methodName, Object... params) throws Exception {
Method[] allMethods = clazz.getDeclaredMethods();
if (allMethods != null && allMethods.length > 0) {
Class[] paramClasses = Arrays.stream(params).map(p -> p != null ? p.getClass() : null).toArray(Class[]::new);
for (Method method : allMethods) {
String currentMethodName = method.getName();
if (!currentMethodName.equals(methodName)) {
continue;
}
Type[] pTypes = method.getParameterTypes();
if (pTypes.length == paramClasses.length) {
boolean goodMethod = true;
int i = 0;
for (Type pType : pTypes) {
if (!ClassUtils.isAssignable(paramClasses[i++], (Class<?>) pType)) {
goodMethod = false;
break;
}
}
if (goodMethod) {
method.setAccessible(true);
return (T) method.invoke(instance, params);
}
}
}
throw new MethodNotFoundException("There are no methods found with name " + methodName + " and params " +
Arrays.toString(paramClasses));
}
throw new MethodNotFoundException("There are no methods found with name " + methodName);
}
Method uses apache ClassUtils for checking compatibility of autoboxed params
One more variant is using very powerfull JOOR library https://github.com/jOOQ/jOOR
MyObject myObject = new MyObject()
on(myObject).get("privateField");
It allows to modify any fields like final static constants and call yne protected methods without specifying concrete class in the inheritance hierarhy
<!-- https://mvnrepository.com/artifact/org.jooq/joor-java-8 -->
<dependency>
<groupId>org.jooq</groupId>
<artifactId>joor-java-8</artifactId>
<version>0.9.7</version>
</dependency>
You can use Manifold's @Jailbreak for direct, type-safe Java reflection:
@Jailbreak Foo foo = new Foo();
foo.callMe();
public class Foo {
private void callMe();
}
@Jailbreak
unlocks the foo
local variable in the compiler for direct access to all the members in Foo
's hierarchy.
Similarly you can use the jailbreak() extension method for one-off use:
foo.jailbreak().callMe();
Through the jailbreak()
method you can access any member in Foo
's hierarchy.
In both cases the compiler resolves the method call for you type-safely, as if a public method, while Manifold generates efficient reflection code for you under the hood.
Alternatively, if the type is not known statically, you can use Structural Typing to define an interface a type can satisfy without having to declare its implementation. This strategy maintains type-safety and avoids performance and identity issues associated with reflection and proxy code.
Discover more about Manifold.
참고URL : https://stackoverflow.com/questions/880365/any-way-to-invoke-a-private-method
'IT박스' 카테고리의 다른 글
오류 : BinderProxy @ 45d459c0이 유효하지 않습니다. (0) | 2020.06.29 |
---|---|
고착 된 / 사실적인 Resque 직원을 어떻게 정리합니까? (0) | 2020.06.29 |
Nexus 4에서 USB 디버깅 모드를 찾아서 켜는 방법 (0) | 2020.06.29 |
C ++에서 객체 유형 찾기 (0) | 2020.06.29 |
Gradle : 태스크 ': processDebugManifest'에 대한 실행 실패 (0) | 2020.06.29 |