如何通过反射找到方法的字符串名称?
例如给定:
class Car{
public void getFoo(){
}
}
我想要获取字符串"getFoo",类似于以下内容:
Car.getFoo.toString() == "getFoo" // TRUE
如何通过反射找到方法的字符串名称?
例如给定:
class Car{
public void getFoo(){
}
}
我想要获取字符串"getFoo",类似于以下内容:
Car.getFoo.toString() == "getFoo" // TRUE
你可以这样获得字符串:
Car.class.getDeclaredMethods()[0].getName();
这适用于您类中的单个方法情况。如果您想遍历所有已声明的方法,则需要迭代Car.class.getDeclaredMethods()
返回的数组:
for (Method method : Car.class.getDeclaredMethods()) {
String name = method.getName();
}
如果你想查看所有方法,应该使用getDeclaredMethods()
,而getMethods()
仅返回公共方法。
最后,如果你想要查看当前正在执行的方法名,你应该使用这段代码:
Thread.currentThread().getStackTrace()[1].getMethodName();
这将获取当前线程的堆栈跟踪并返回其顶部方法的名称。
由于方法本身不是对象,因此它们没有直接属性(就像您在诸如JavaScript之类的语言中期望的一等函数一样)。
您能做的最接近的方法是调用Car.class.getMethods()
。
Car.class
是一个Class
对象,您可以使用它来调用任何反射方法。
然而,据我所知,一个方法无法识别自己。
所以,您想获取当前正在执行的方法的名称?这里有一种相当丑陋的方法:
Exception e = new Exception();
e.fillInStackTrace();
String methodName = e.getStackTrace()[0].getMethodName();
请查看此线程:
它提供了一些其他的解决方案 - 例如:
String name = new Object(){}.getClass().getEnclosingMethod().getName();
使用Java 8,您可以仅用几行代码(几乎)不需要任何其他库来完成此操作。关键是将您的方法转换为可序列化的lambda表达式。因此,您只需定义一个简单的接口,如下所示:
@FunctionalInterface
public interface SerializableFunction<I, O> extends Function<I, O>, Serializable {
// Combined interface for Function and Serializable
}
现在,我们需要将lambda表达式转换成SerializedLambda
对象。显然,Oracle并不希望我们这样做,所以要谨慎对待...由于所需方法是私有的,因此我们需要使用反射来调用它:
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();
}
@Test
public void testNameOf() throws Throwable {
assertEquals("getName", nameOf(MyClassTest::getName));
}
我还没有使用Java 9的模块系统检查过这个问题,所以需要说明的是,在更近期的Java版本中可能会更加棘手...
试试这个,
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);
}
}
}
Class.methodName.toString()
,直接使用"methodName"
即可。Class#getDeclaredMethods()
来获取类中的所有方法。