Sto lavorando ad alcune invocazioni dinamiche del codice tramite un interprete e sto entrando nelle brutte aree di risoluzione dei metodi come discusso in JLS section 15.12.Java: risoluzione del metodo di runtime
Il metodo "facile" per scegliere un metodo è quando si conoscono i tipi esatti di tutti gli argomenti, a quel punto è possibile utilizzare Class.getDeclaredMethod(String name, Class[] parameterTypes)
. Forse devi controllare l'accessibilità del metodo e le superclassi/superinterfacce della classe.
Ma questo non copre qualsiasi dei seguenti casi, quindi è una specie di inutile:
- boxe/primitive unboxing
- sottotipi
- varargs
- un argomento null (che può essere qualsiasi tipo, a meno che l'interprete non sappia diversamente, in fase di compilazione qualsiasi ambiguità verrebbe eliminata rilasciando null a una classe/interfaccia)
- conversione di tipo primitivo (non parte di Java, ma consentita nel contesto delle lingue - ad es. Rinoceronte JavaScript dove tutti i numeri sono virgola mobile, in modo che il codice Java potrebbe richiedere un
int
ma il chiamante passa in un numero che è o unint
odouble
)
(vedi sotto per un breve esempio del primo tre)
così ora devo scrivere la mia libreria risoluzione metodo ...
c'è qualche libreria quadro ben noto per aiutare in questo?
package com.example.test.reflect;
import java.lang.reflect.Method;
public class MethodResolutionTest {
public void compute(int i) { /* implementation... */ }
public void compute(Long l) { /* implementation... */ }
public void compute(Object obj) { /* implementation... */ }
public void compute(String... strings) { /* implementation... */ }
public static void main(String[] args) {
Class<?> cl = MethodResolutionTest.class;
/* these succeed */
findAndPrintMethod(cl, "compute", int.class);
findAndPrintMethod(cl, "compute", Long.class);
findAndPrintMethod(cl, "compute", Object.class);
findAndPrintMethod(cl, "compute", String[].class);
/* these fail */
findAndPrintMethod(cl, "compute", Integer.class);
findAndPrintMethod(cl, "compute", long.class);
findAndPrintMethod(cl, "compute", MethodResolutionTest.class);
findAndPrintMethod(cl, "compute", String.class, String.class);
}
private static void findAndPrintMethod(Class<?> objectClass,
String methodName, Class<?>... parameterTypes)
{
try {
Method method = findMethod(objectClass, methodName,
parameterTypes);
System.out.println(method.toString());
}
catch (SecurityException e) {
e.printStackTrace();
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
private static Method findMethod(Class<?> objectClass,
String methodName, Class<?>[] parameterTypes)
throws SecurityException, NoSuchMethodException
{
return objectClass.getDeclaredMethod(methodName, parameterTypes);
}
}
[Questa risposta gestisce alcuni casi come sottotipi] (http://stackoverflow.com/questions/2580665/java-getmethod-with-superclass-parameters-in-method/2580699#2580699). –
@ Jonathon: So di isAssignableFrom. Ho qualcosa di homegrown che funziona con sottotipi e boxe/unboxing. Poi ho iniziato a varargare e mi sono fatto male, e ho pensato, "Aspetta un attimo, perché sto facendo questo?" quindi sono specificamente alla ricerca di una libreria preesistente. (O almeno una buona serie di casi di test preesistenti) Altrimenti posso farlo da solo, ma è un grande dolore. –
A meno che non trovi una dolce biblioteca, penso che qualsiasi cosa tu faccia sarà brutta e difficile da leggere. –