35

How can I find out through reflection what is the string name of the method?

For example given:

class Car{
   public void getFoo(){
   }
}

I want to get the string "getFoo", something like the following:

 Car.getFoo.toString() == "getFoo" // TRUE
jjnguy
  • 136,852
  • 53
  • 295
  • 323
Andriy Drozdyuk
  • 58,435
  • 50
  • 171
  • 272

7 Answers7

41

You can get the String like this:

Car.class.getDeclaredMethods()[0].getName();

This is for the case of a single method in your class. If you want to iterate through all the declared methods, you'll have to iterate through the array returned by Car.class.getDeclaredMethods():

for (Method method : Car.class.getDeclaredMethods()) {
    String name = method.getName();
}

You should use getDeclaredMethods() if you want to view all of them, getMethods() will return only public methods.

And finally, if you want to see the name of the method, which is executing at the moment, you should use this code:

Thread.currentThread().getStackTrace()[1].getMethodName();

This will get a stack trace for the current thread and return the name of the method on its top.

Dale Wilson
  • 9,166
  • 3
  • 34
  • 52
Malcolm
  • 41,014
  • 11
  • 68
  • 91
  • Thanks, i'm afraid I don't really want to be tied down to the "one-method-per-class" thing... – Andriy Drozdyuk Jun 11 '10 at 14:19
  • You can get all of the methods of the class or just the method being executed at the moment. See my edits. :) – Malcolm Jun 11 '10 at 14:21
  • Thanks. Curious. But I do need a name of a method that is Not currently executing. It seems like java does not provide a way to do that... – Andriy Drozdyuk Jun 11 '10 at 14:29
  • I don't get it, you want to get the name of the method, but how are you gonna specify the method? – Malcolm Jun 11 '10 at 14:36
  • 7
    Hi , by doing Thread.currentThread().getStackTrace()[0].getMethodName(); yo get the first method in the stack , which at that moment is "getStackTrace" ,you should do Thread.currentThread().getStackTrace()[1].getMethodName(); in order to get the one which have the code line, if you want to decouple this method so you dont have to duplicate it in each place i suggest to make it static in a class and call it with [2], i haven't tryed thought i seems logic for it to work. – Lau Llobet Jun 09 '14 at 08:51
  • instead of Thread.currentThread().getStackTrace()[0].getMethodName();, I had better luck with Thread.currentThread().getStackTrace()[1].getMethodName(); :) it should work everytime, although I haven't tried it in a constructor or lazy loading situation – Alexander Mills Jun 20 '15 at 06:08
  • 2
    On Android the method name is in the third element: Thread.currentThread().getStackTrace()[2].getMethodName() – Godfrey Duke Sep 06 '16 at 21:20
  • @GodfreyDuke Well, I outlined the general strategy, you have to experiment a little on the target platform. It may even be that different Android versions behave a bit differently. – Malcolm Sep 06 '16 at 22:46
  • Thanks, This one works perfect Thread.currentThread().getStackTrace()[1].getMethodName(); – Vinayak Dornala Aug 23 '17 at 16:18
24

Since methods aren't objects themselves, they don't have direct properties (like you would expect with first-class functions in languages like JavaScript).

The closest you can do is call Car.class.getMethods()

Car.class is a Class object which you can use to invoke any of the reflection methods.

However, as far as I know, a method is not able to identify itself.

Matt
  • 43,482
  • 6
  • 101
  • 102
  • 1
    with Java 9 or later we can now use a [`StackWalker`](https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/lang/StackWalker.html) to find the actual class and method names (I know, 12 years *late*) – user16320675 Nov 02 '22 at 22:38
15

So, you want to get the name of the currently executing method? Here's a somewhat ugly way to do that:

Exception e = new Exception();
e.fillInStackTrace();
String methodName = e.getStackTrace()[0].getMethodName();
Jesper
  • 202,709
  • 46
  • 318
  • 350
  • 1
    Actually, this.getClass().getEnclosingMethod() works just fine! – mjs Jul 11 '14 at 11:10
  • momomo, no, it doesn't. class Test { @Test public void testReflection() { assert (this.getClass().getEnclosingMethod() == null); } } – Hazel T Apr 28 '17 at 18:40
9

Look into this thread:

Getting the name of the currently executing method

It offers some more solutions - for example:

String name = new Object(){}.getClass().getEnclosingMethod().getName();
olivmir
  • 692
  • 10
  • 29
4

With Java 8, you can do this with a few lines of code (almost) without any additional libraries. The key is to convert your method into a serialisable lambda expression. Therefore, you can just define a simple interface like this:

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

Now, we need to convert our lambda expression into a SerializedLambda object. Apparently, Oracle does not really want us to do that, so take this with a grain of salt... As the required method is private, we need to invoke it using reflections:

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

I'm using Springs ReflectionUtils class here for simplicity, but you can of course replace this by manually looping through all superclasses and use getDeclaredMethod to find the writeReplace method.

And this is it already, now you can use it like this:

@Test
public void testNameOf() throws Throwable {
  assertEquals("getName", nameOf(MyClassTest::getName));
}

I haven't checked this with Java 9s module system, so as a little disclaimer it might be more tricky to do this with more recent Java versions...

Jan Gassen
  • 3,406
  • 2
  • 26
  • 44
  • When implementing "ReflectionUtils.findMethod" be sure to use "getDeclaredMethod("writeReplace")" or "getDeclaredMethods()" not "getMethod("writeReplace")" or "getMethods()" – James Wasson Jun 20 '19 at 18:31
1

try this,

 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);
            }
        }
    }
zhy2002
  • 389
  • 5
  • 11
0

Wait, since you already know the method name, can't you just type it as a string?

Instead of (pseudo) Class.methodName.toString(), just use "methodName".

Otherwise you can use Class#getDeclaredMethods() to get all the methods in a class

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140