【发布时间】:2010-06-11 13:59:07
【问题描述】:
如何通过反射找出方法的字符串名称是什么?
例如给出:
class Car{
public void getFoo(){
}
}
我想得到字符串“getFoo”,如下所示:
Car.getFoo.toString() == "getFoo" // TRUE
【问题讨论】:
标签: java reflection
如何通过反射找出方法的字符串名称是什么?
例如给出:
class Car{
public void getFoo(){
}
}
我想得到字符串“getFoo”,如下所示:
Car.getFoo.toString() == "getFoo" // TRUE
【问题讨论】:
标签: java reflection
你可以像这样得到字符串:
Car.class.getDeclaredMethods()[0].getName();
这是针对您的类中的单个方法的情况。如果要遍历所有声明的方法,则必须遍历 Car.class.getDeclaredMethods() 返回的数组:
for (Method method : Car.class.getDeclaredMethods()) {
String name = method.getName();
}
如果你想查看所有这些,你应该使用getDeclaredMethods(),getMethods() 将只返回 public 方法。
最后,如果您想查看当前正在执行的方法的名称,您应该使用以下代码:
Thread.currentThread().getStackTrace()[1].getMethodName();
这将获取当前线程的堆栈跟踪,并在其顶部返回方法的名称。
【讨论】:
由于方法本身不是对象,因此它们没有直接属性(就像 JavaScript 等语言中的一流函数所期望的那样)。
您最接近的方法是致电Car.class.getMethods()
Car.class 是一个Class 对象,您可以使用它来调用任何反射方法。
但是,据我所知,方法无法识别自己。
【讨论】:
那么,你想获取当前正在执行的方法的名称吗?这是一种有点丑陋的方法:
Exception e = new Exception();
e.fillInStackTrace();
String methodName = e.getStackTrace()[0].getMethodName();
【讨论】:
看看这个帖子:
Getting the name of the currently executing method
它提供了更多的解决方案——例如:
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();
}
为了简单起见,我在这里使用 Springs ReflectionUtils 类,但您当然可以通过手动循环所有超类来替换它,并使用 getDeclaredMethod 找到 writeReplace 方法。
这已经是它了,现在你可以像这样使用它了:
@Test
public void testNameOf() throws Throwable {
assertEquals("getName", nameOf(MyClassTest::getName));
}
我没有用 Java 9s 模块系统检查过这一点,所以作为一个小免责声明,使用更新的 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()来获取一个类中的所有方法
【讨论】: