Java: How to check if a method is overridden, using reflection
Asked Answered
G

1

6

I need to do some processing to determine the dependencies of JSR-330 annotated classes, using reflection.

I am fully aware of all JSR-330 compliant IoC containers, like Spring, Guice or PicoContainer. However, what I need is not to resolve and inject dependencies, but to identify them.

That basically means I need to implement the JSR-330 implementation, at least when it comes to reflective class "parsing".

There is one part of the JSR-330 specification which I find slightly troublesome to implement:

A method annotated with @Inject that overrides another method annotated with @Inject will only be injected once per injection request per instance. A method with no @Inject annotation that overrides a method annotated with @Inject will not be injected.

That means that subclasses can redefine the autowiring contract of their base class, as well as hook into the injection flow (through polymorphism).

Here comes my question: Given a class hierarchy, is there an easy way to check whether a method at some part of the hierarchy is overridden further down the hierarchy?

The simplest way I would do this in my case is with recursion from the leaf of the hierarchy:

private List<Method> getInjectableMethods(final Class<?> clazz) {
    // recursive stop condition
    if(clazz == null) {
        return emptyList();
    }

    // recursively get injectable methods from superclass
    final List<Method> allInjectableMethods = newLinkedList(getInjectableMethods(clazz.getSuperclass()));
    final List<Method> injectableMethods = newArrayList();

    // any overridden method will be present in the final list only if it is injectable in clazz
    for (final Method method : clazz.getDeclaredMethods()) {
        removeIf(allInjectableMethods, Methods.Predicates.overriddenBy(method));
        if (isInjectable(method)) {
            injectableMethods.add(method);
        }
    }
    allInjectableMethods.addAll(injectableMethods);

    return allInjectableMethods;
}

As for the overriddenBy Guava-like Predicate, I would check that:

  • The methods defining classes are in an isAssignableFrom relation
  • The methods name is the same
  • The methods formal parameters are the same

The resulting complexity is O(n^2) with regard to the number of methods in the hierarchy.

I was wondering if there was some easier or more efficient way to achieve it, or any libraries with such functionality. I've looked unsuccessfully in both Guava and Apache Commons...

Gomes answered 12/3, 2012 at 18:37 Comment(4)
Google Reflections maybe? code.google.com/p/reflectionsCumulous
I looked through the javadocs and didn't find anything for checking for method override. Nice library though, I'll keep it in mind!Gomes
At worst it will make implementing your algorithm easier. :)Cumulous
You might want to read this: https://mcmap.net/q/544852/-how-to-quickly-determine-if-a-method-is-overridden-in-java. Also check this answer: https://mcmap.net/q/582108/-java-how-to-find-if-a-method-is-overridden-from-base-class-duplicate. Using the first answer you could build up the override tree from the leafs upwards in time O(n) as you would have to check each method only once.Lisbethlisbon
Z
1

Unfortunately, class graph is navigable only in root direction - so there is no way to find all derived classes except to check all classes available to certain classloader. IoC containers do not have this problem, because they always know concrete implementation ( it is part of configuration )

Inheritance trees are usually built by IDEs, but AFAIUK they use brite force indexing over all available sources / classes ( you may look into sources of community editio of InteliiJ IDEA for clues )

Zooplankton answered 13/3, 2012 at 14:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.