【问题标题】:How to get string name of a method in java?如何在java中获取方法的字符串名称?
【发布时间】:2010-06-11 13:59:07
【问题描述】:

如何通过反射找出方法的字符串名称是什么?

例如给出:

class Car{
   public void getFoo(){
   }
}

我想得到字符串“getFoo”,如下所示:

 Car.getFoo.toString() == "getFoo" // TRUE

【问题讨论】:

    标签: java reflection


    【解决方案1】:

    你可以像这样得到字符串:

    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();
    

    这将获取当前线程的堆栈跟踪,并在其顶部返回方法的名称。

    【讨论】:

    • 谢谢,恐怕我真的不想被束缚在“每个班级一个方法”的事情上......
    • 您可以获取该类的所有方法,也可以只获取当前正在执行的方法。请参阅我的编辑。 :)
    • 谢谢。好奇的。但我确实需要一个当前未执行的方法的名称。似乎java没有提供一种方法来做到这一点......
    • 嗨,通过执行 Thread.currentThread().getStackTrace()[0].getMethodName();你得到堆栈中的第一个方法,当时是“getStackTrace”,你应该做 Thread.currentThread().getStackTrace()[1].getMethodName();为了获得具有代码行的那个,如果你想解耦这个方法,所以你不必在每个地方复制它我建议在一个类中使它成为静态并用 [2] 调用它,我没有尝试过认为我似乎符合逻辑。
    • 在 Android 上,方法名称位于第三个元素中:Thread.currentThread().getStackTrace()[2].getMethodName()
    【解决方案2】:

    由于方法本身不是对象,因此它们没有直接属性(就像 JavaScript 等语言中的一流函数所期望的那样)。

    您最接近的方法是致电Car.class.getMethods()

    Car.class 是一个Class 对象,您可以使用它来调用任何反射方法。

    但是,据我所知,方法无法识别自己。

    【讨论】:

      【解决方案3】:

      那么,你想获取当前正在执行的方法的名称吗?这是一种有点丑陋的方法:

      Exception e = new Exception();
      e.fillInStackTrace();
      String methodName = e.getStackTrace()[0].getMethodName();
      

      【讨论】:

      • 其实 this.getClass().getEnclosureMethod() 就可以了!
      • momomo,不,它没有。类测试 { @Test public void testReflection() { 断言 (this.getClass().getEnclosureMethod() == null); } }
      【解决方案4】:

      看看这个帖子:

      Getting the name of the currently executing method

      它提供了更多的解决方案——例如:

      String name = new Object(){}.getClass().getEnclosingMethod().getName();
      

      【讨论】:

        【解决方案5】:

        使用 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 版本可能会更棘手......

        【讨论】:

        • 在实现“ReflectionUtils.findMethod”时,一定要使用“getDeclaredMethod("writeReplace")”或“getDeclaredMethods()”而不是“getMethod("writeReplace")”或“getMethods()”跨度>
        【解决方案6】:

        试试这个,

         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);
                    }
                }
            }
        

        【讨论】:

          【解决方案7】:

          等等,既然你已经知道方法名,你就不能直接输入一个字符串吗?

          而不是(伪)Class.methodName.toString(),只需使用"methodName"。

          否则你可以使用Class#getDeclaredMethods()来获取一个类中的所有方法

          【讨论】:

          • 我不想使用字符串。我将来可能会重构我的方法名称。
          • IDE 能够在重构时查看字符串
          猜你喜欢
          • 2011-09-15
          • 1970-01-01
          • 2016-05-15
          • 2020-06-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-05
          相关资源
          最近更新 更多