Wie kann ich durch Nachdenken herausfinden, wie der Name der Methode lautet?
Zum Beispiel gegeben:
class Car{
public void getFoo(){
}
}
Ich möchte den String "getFoo" bekommen, etwa wie folgt:
Car.getFoo.toString() == "getFoo" // TRUE
Da Methoden keine Objekte selbst sind, haben sie keine direkten Eigenschaften (wie Sie es von erstklassigen Funktionen in Sprachen wie JavaScript erwarten würden).
Am nächsten können Sie anrufen Car.class.getMethods()
Car.class
ist ein Objekt Class
, mit dem Sie eine der Reflexionsmethoden aufrufen können.
Eine Methode kann sich meines Wissens jedoch nicht identifizieren.
Sie können den String wie folgt erhalten:
Car.class.getDeclaredMethods()[0].getName();
Dies gilt für eine einzelne Methode in Ihrer Klasse. Wenn Sie alle deklarierten Methoden durchlaufen möchten, müssen Sie das von Car.class.getDeclaredMethods()
zurückgegebene Array durchlaufen:
for (Method method : Car.class.getDeclaredMethods()) {
String name = method.getName();
}
Sie sollten getDeclaredMethods()
verwenden, wenn Sie alle anzeigen möchten. getMethods()
gibt nur public Methods zurück.
Und schließlich, wenn Sie den Namen der Methode sehen möchten, die gerade ausgeführt wird, sollten Sie diesen Code verwenden:
Thread.currentThread().getStackTrace()[1].getMethodName();
Dadurch wird eine Stapelablaufverfolgung für den aktuellen Thread abgerufen und der Name der Methode wird oben angezeigt.
Sie möchten also den Namen der aktuell ausgeführten Methode ermitteln? Hier ist ein etwas hässlicher Weg, das zu tun:
Exception e = new Exception();
e.fillInStackTrace();
String methodName = e.getStackTrace()[0].getMethodName();
versuche dies,
import Java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[]) {
try {
Class c = Class.forName(args[0]);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
} catch (Throwable e) {
System.err.println(e);
}
}
}
Mit Java 8 können Sie dies mit wenigen Zeilen Code (fast) ohne zusätzliche Bibliotheken tun. Der Schlüssel ist, Ihre Methode in einen serialisierbaren Lambda-Ausdruck zu konvertieren. Daher können Sie einfach eine einfache Schnittstelle wie folgt definieren:
@FunctionalInterface
public interface SerializableFunction<I, O> extends Function<I, O>, Serializable {
// Combined interface for Function and Serializable
}
Nun müssen wir unseren Lambda-Ausdruck in ein SerializedLambda
-Objekt konvertieren. Anscheinend möchte Oracle nicht, dass wir das tun, also nehmen Sie dies mit einem Salzkorn ... Da die erforderliche Methode privat ist, müssen wir sie mit Reflexionen aufrufen:
private static final <T> String nameOf(SerializableFunction<T, ?> lambda) {
Method findMethod = ReflectionUtils.findMethod(lambda.getClass(), "writeReplace");
findMethod.setAccessible(true);
SerializedLambda invokeMethod = (SerializedLambda) ReflectionUtils.invokeMethod(findMethod, lambda);
return invokeMethod.getImplMethodName();
}
Ich verwende hier die Springs ReflectionUtils
-Klasse zur Vereinfachung. Sie können dies natürlich ersetzen, indem Sie alle Superklassen manuell durchlaufen und getDeclaredMethod
verwenden, um die writeReplace
-Methode zu finden.
Und das ist es schon, jetzt kannst du es so benutzen:
@Test
public void testNameOf() throws Throwable {
assertEquals("getName", nameOf(MyClassTest::getName));
}
Ich habe dies nicht mit dem Java 9s-Modulsystem überprüft, daher kann es als kleiner Haftungsausschluss mit neueren Java-Versionen schwieriger sein ...
Warten Sie, da Sie den Methodennamen bereits kennen, können Sie ihn nicht einfach als Zeichenfolge eingeben?
Anstelle von (Pseudo) Class.methodName.toString()
verwenden Sie einfach "methodName
".
Ansonsten können Sie Class#getDeclaredMethods()
verwenden, um alle Methoden in einer Klasse abzurufen
Schau in diesen Thread:
Den Namen der aktuell ausgeführten Methode abrufen
Es bietet einige weitere Lösungen an, zum Beispiel:
String name = new Object(){}.getClass().getEnclosingMethod().getName();