8

Question

How can you get the names of all the methods of a class without the inherited methods?

Example

def methods = MyClass.methods.collect { it.name }
println methods.each { println it }
assert ["method1_static_void", "method2_static_String", "method3_void", "method4_String"].sort() == methods.sort()


class MyClass {
    public static void method1_static_void() {}
    public static String method2_static_String() {}
    public void method3_void() {}
    private String method4_String() {}
}

Expected output

method1_static_void
method2_static_String
method3_void
method4_String

Actual output

setProperty
getProperty
super$1$wait
super$1$wait
super$1$wait
super$1$clone
getMetaClass
invokeMethod
setMetaClass
__$swapInit
method3_void
method1_static_void
method2_static_String
this$2$method4_String
this$dist$invoke$1
this$dist$set$1
this$dist$get$1
super$1$toString
super$1$notify
super$1$notifyAll
super$1$getClass
super$1$equals
super$1$hashCode
super$1$finalize
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll
[setProperty, getProperty, super$1$wait, super$1$wait, super$1$wait, super$1$clone, getMetaClass, invokeMethod, setMetaClass, __$swapInit, method3_void, method1_static_void, method2_static_String, this$2$method4_String, this$dist$invoke$1, this$dist$set$1, this$dist$get$1, super$1$toString, super$1$notify, super$1$notifyAll, super$1$getClass, super$1$equals, super$1$hashCode, super$1$finalize, wait, wait, wait, equals, toString, hashCode, getClass, notify, notifyAll]
Assertion failed: 

assert ["method1_static_void", "method2_static_String", "method3_void", "method4_String"] == methods
                                                                                          |  |
                                                                                          |  [setProperty, getProperty, super$1$wait, super$1$wait, super$1$wait, super$1$clone, getMetaClass, invokeMethod, setMetaClass, __$swapInit, method3_void, method1_static_void, method2_static_String, this$2$method4_String, this$dist$invoke$1, this$dist$set$1, this$dist$get$1, super$1$toString, super$1$notify, super$1$notifyAll, super$1$getClass, super$1$equals, super$1$hashCode, super$1$finalize, wait, wait, wait, equals, toString, hashCode, getClass, notify, notifyAll]
                                                                                          false

Google findings

Lernkurve
  • 20,203
  • 28
  • 86
  • 118

1 Answers1

19

Instead of:

def methods = MyClass.methods.collect { it.name }

You just need the declared non-synthetic methods:

def methods = MyClass.declaredMethods.findAll { !it.synthetic }.name

Groovy 3+

After a change in Groovy 3 (see Simon's comment below) you will need to do:

def methods = MyClass.declaredMethods.findAll {
    !it.synthetic && !it.getAnnotation(groovy.transform.Internal) 
}.name
tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • This good, but the `!it.synthetic` part doesn't quite work - it returns `getMetaClass` and `setMetaClass` despite the fact I never declared those methods on my class, Groovy has synthesised them automatically. Apparently that is an intentional decision – https://issues.apache.org/jira/browse/GROOVY-9636 – Simon Kissane Sep 23 '21 at 02:50