Как получить строковое имя метода в Java? - PullRequest
26 голосов
/ 11 июня 2010

Как узнать через отражение, как называется строка метода?

Например, например:

class Car{
   public void getFoo(){
   }
}

Я хочу получить строку "getFoo", что-то вродеследующее:

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

Ответы [ 7 ]

35 голосов
/ 11 июня 2010

Вы можете получить строку следующим образом:

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

Получит трассировку стека для текущего потока и вернет имя метода в его верхнюю часть.

20 голосов
/ 11 июня 2010

Поскольку методы сами по себе не являются объектами, они не имеют прямых свойств (как можно было бы ожидать от первоклассных функций в таких языках, как JavaScript).

Самое близкое, что вы можете сделать, это позвонить Car.class.getMethods()

Car.class - это объект Class, который можно использовать для вызова любого из методов отражения.

Однако, насколько я знаю, метод не может идентифицировать себя.

14 голосов
/ 11 июня 2010

Итак, вы хотите получить имя текущего выполняемого метода?Вот несколько уродливый способ сделать это:

Exception e = new Exception();
e.fillInStackTrace();
String methodName = e.getStackTrace()[0].getMethodName();
1 голос
/ 13 декабря 2018

С Java 8 вы можете сделать это с помощью нескольких строк кода (почти) без каких-либо дополнительных библиотек. Ключ должен преобразовать ваш метод в сериализуемое лямбда-выражение. Следовательно, вы можете просто определить простой интерфейс, например:

@FunctionalInterface
public interface SerializableFunction<I, O> extends Function<I, O>, Serializable {
  // Combined interface for Function and Serializable
}

Теперь нам нужно преобразовать наше лямбда-выражение в 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 ...

1 голос
/ 13 августа 2018

Загляните в эту ветку:

Получение имени выполняемого в настоящее время метода

Он предлагает еще несколько решений - например:

String name = new Object(){}.getClass().getEnclosingMethod().getName();
1 голос
/ 11 июня 2010

попробуйте это,

 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);
            }
        }
    }
0 голосов
/ 11 июня 2010

Подождите, так как вы уже знаете имя метода, вы не можете просто ввести его в виде строки?

Вместо (псевдо) Class.methodName.toString() просто используйте "methodName ".

В противном случае вы можете использовать Class#getDeclaredMethods(), чтобы получить все методы в классе

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...