Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8029459

(reflect) getMethods returns methods that are not members of the class

    Details

      Description

      Dan writes:

      ---

      To illustrate, the JDK 7 implementation of getMethods includes the following:
      1) The class's/interface's declared (public) methods
      2) The getMethods() of the superclass (if this is a class), minus any that have a match in (1)
      3) The getMethods() of each superinterface, minus any that have a match in (1) or a _concrete_ match in (2)

      So, for example, as expected:
      interface I { void m(); }
      interface J extends I { void m(); }
      interface K extends J {}
      K.class.getMethods() = [ J.m ]

      But:
      interface I { void m(); }
      interface J extends I { void m(); }
      interface K extends ***I,*** J {}
      K.class.getMethods() = [ I.m, J.m ]

      This is consistent with a reasonable reading of JLS 7 (though it is vague)*, but conflicts with JLS 8. We changed the 8 spec because, unlike abstract methods, inheriting two conflicting default methods is a compiler error, and that should be avoided.

      [* There was a time when I thought the current behavior could be considered a 7 bug, but having experimented with it more, I no longer think that's the case. This is a new issue in 8.]

      An implementation of getMethods consistent with JLS 8 would include the following (see Lambda Spec, Part H, 9.4.1 and 8.4.8):
      1) The class's/interface's declared (public) methods
      2) The getMethods() of the superclass (if this is a class), minus any that have a match in (1)
      3) The getMethods() of each superinterface, minus any that have a match in (1) or a _concrete_ match in (2) ***or a match from a more-specific class/interface in (2) or (3)***

      However, there is a compatibility concern: the behavior of K.class.getMethods in the second example above changes. How much do we care about this? The spec change was made with the understanding that this was simply an internal change to an intermediate result, without observable consequences. Reflection exposes that intermediate result. But, even so, client code should not be depending on the rather vague notion of how many identical abstract methods are members of a class.

      ---

      That is, the spec changed in 8 but the implementation (which was correct up through 7) has not changed.

      This issue is for the general case, there is a separate issue: JDK-8029674 for the case of default methods, which since new to the platform, has less of a compatibility baggage.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                dlsmith Dan Smith
                Reporter:
                jfranck Joel Borggrén-Franck
              • Votes:
                0 Vote for this issue
                Watchers:
                9 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: