variable usar una programa otro otra objeto llamar formulario ejecutar dentro como clases clase java reflection private

java - usar - ¿Alguna forma de invocar un método privado?



llamar a un objeto de otra clase java (6)

Tengo una clase que usa XML y reflexión para devolver Object s a otra clase.

Normalmente, estos objetos son subcampos de un objeto externo, pero ocasionalmente es algo que quiero generar sobre la marcha. He intentado algo como esto, pero fue en vano. Creo que es porque Java no le permitirá acceder a métodos private para la reflexión.

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

Si el método proporcionado es private , falla con una NoSuchMethodException . Podría resolverlo haciendo public el método o haciendo otra clase para derivarlo.

Para resumir, me preguntaba si había una forma de acceder a un método private través de la reflexión.


Permítanme proporcionar un código completo para los métodos de ejecución protegida a través de la reflexión. Es compatible con cualquier tipo de parámetros, incluidos genéricos, params autoboxados y valores nulos

@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 utiliza apache ClassUtils para verificar la compatibilidad de los params autoboxados


Puede invocar el método privado con la reflexión. Modificando el último bit del código publicado:

Method method = object.getClass().getDeclaredMethod(methodName); method.setAccessible(true); Object r = method.invoke(object);

Hay un par de advertencias. Primero, getDeclaredMethod solo encontrará el método declarado en la Class actual, no heredado de supertipos. Por lo tanto, recorra la jerarquía de clases concretas si es necesario. En segundo lugar, un SecurityManager puede evitar el uso del método setAccessible . Por lo tanto, es posible que deba ejecutarse como una PrivilegedAction (utilizando AccessController o Subject ).


Si el método acepta un tipo de datos no primitivo, se puede usar el siguiente método para invocar un método privado de cualquier clase:

public static Object genericInvokMethod(Object obj, String methodName, int paramCount, Object... params) { Method method; Object requiredObj = null; Object[] parameters = new Object[paramCount]; Class<?>[] classArray = new Class<?>[paramCount]; for (int i = 0; i < paramCount; i++) { parameters[i] = params[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; }

Los parámetros aceptados son obj, methodName, el recuento de los parámetros aceptados y los parámetros. Por ejemplo

public class Test { private String concatString(String a, String b) { return (a+b); } }

El método concatString se puede invocar como

Test t = new Test(); String str = (String) genericInvokMethod(t, "concatString", 2, "Hello", "Mr.x");


Una variante más es el uso de la biblioteca JOOR muy poderosa https://github.com/jOOQ/jOOR

MyObject myObject = new MyObject() on(myObject).get("privateField");

Permite modificar cualquier campo como las constantes estáticas finales y llamar a los métodos protegidos yne sin especificar una clase concreta en la jerarquía de herencia

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


Use getDeclaredMethod() para obtener un objeto Method privado y luego use method.setAccessible() para permitir que realmente lo llame.


puede hacerlo utilizando ReflectionTestUtils of Sring (org.springframework.test.util.ReflectionTestUtils)

ReflectionTestUtils.invokeMethod(instantiatedObject,"methodName",argument);

Ejemplo: si tienes una clase con un método privado "square (int x)"

Calculator calculator = new Calculator(); ReflectionTestUtils.invokeMethod(calculator,"square",10);