java - varargs - vararg kotlin
Cómo trabajar con varargs y reflexión (2)
Pregunta simple, ¿cómo funciona este código?
public class T {
public static void main(String[] args) throws Exception {
new T().m();
}
public // as mentioned by Bozho
void foo(String... s) {
System.err.println(s[0]);
}
void m() throws Exception {
String[] a = new String[]{"hello", "kitty"};
System.err.println(a.getClass());
Method m = getClass().getMethod("foo", a.getClass());
m.invoke(this, (Object[]) a);
}
}
Salida:
class [Ljava.lang.String;
Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
// antes de la edición:
Su problema es el hecho de que getMethod
busca un miembro public
.
Del Class.getMethod
(énfasis mío):
Devuelve un objeto
Method
que refleja el método miembro público especificado de la clase o interfaz representada por este objeto Clase
Así que tienes dos opciones:
- Hacer
public void foo(String... s)
y usargetMethod
- Use
getDeclaredMethod
engetDeclaredMethod
lugar
Tenga en cuenta que existe la misma diferencia para getField/s
frente a getDeclaredField/s
getConstructor/s
frente a getDeclaredConstructor/s
.
// invoke
problema
Esto es particularmente desagradable, pero lo que sucede es que invoke(Object obj, Object... args)
hace complicado si necesita pasar una matriz de tipo de referencia como un único argumento, porque es apto para Object[]
, a pesar de que debería estar envuelto dentro de un new Object[1]
lugar.
Tu puedes hacer:
m.invoke(this, new Object[] {a}); // Bohzo''s solution
Esto pasa por alto el mecanismo vararg. Más sucintamente, también puedes hacer:
m.invoke(this, (Object) a);
La conversión a Object
hace que el mecanismo vararg haga el trabajo de crear la matriz para ti.
El truco también se necesita al pasar un null
como argumento a varargs, y no tiene nada que ver con la reflexión.
public void foo(String... ss) {
System.out.println(ss[0]);
}
foo(null); // causes NullPointerException
foo((String) null); // prints "null"
Test.class.getDeclaredMethod("foo", String[].class);
trabajos. El problema es que getMethod(..)
solo busca en los métodos public
. Desde el javadoc:
Devuelve un objeto Método que refleja el método miembro público especificado de la clase o interfaz representada por este objeto Clase.
Actualización: después de obtener el método con éxito, puede invocarlo usando:
m.invoke(this, new Object[] {new String[] {"a", "s", "d"}});
es decir, crea una nueva matriz de Object
con un elemento: la matriz de String
. Con sus nombres de variable se vería así:
m.invoke(this, new Object[] {a});