【问题标题】:getDeclaredMethods() behaving differently in Java 7 vs. Java 8getDeclaredMethods() 在 Java 7 和 Java 8 中的行为不同
【发布时间】:2014-11-19 09:44:15
【问题描述】:

考虑以下小例子:

package prv.rli.codetest;

import java.lang.reflect.Method;

public class BreakingInterfaces  {
    interface Base {
        BaseFoo foo();
        interface BaseFoo {           
        }
    }

    interface Derived extends Base {
        DerivedFoo foo();
        interface DerivedFoo extends BaseFoo {

        }
    }

    public static void main(String[] args) {       
        dumpDeclaredMethods(Derived.class);
    }

    private static void dumpDeclaredMethods(Class<?> class1) {
        System.out.println("---" + class1.getSimpleName() + "---");
        Method[] methods = class1.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("----------");
    }
}

如果你用 jdk1.7.0.55 编译上面的例子,输出是:

 ---Derived---
public abstract BreakingInterfaces$Derived$DerivedFoo BreakingInterfaces$Derived.foo()
----------

但是当使用 jdk1.8.0.25 时输出是:

---Derived---
public abstract prv.rli.codetest.BreakingInterfaces$Derived$DerivedFoo prv.rli.codetest.BreakingInterfaces$Derived.foo()
public default prv.rli.codetest.BreakingInterfaces$Base$BaseFoo prv.rli.codetest.BreakingInterfaces$Derived.foo()
----------

有谁知道,这是 jdk1.8.0.25 中的一个错误,还是为什么这里会出现公共默认方法?

【问题讨论】:

  • 我在这里猜测,但这可能与接口中方法的 java8 默认实现有关。

标签: java java-8


【解决方案1】:

getDeclaredMethods() 在这里表现正确,因为它准确地告诉你它在类中找到了什么。如果您输入使用 Java 7 目标(或较旧的编译器)编译的 interface,您将看到与 getDeclaredMethods() 的 Java 7 实现的输出没有区别。

编译器的行为不同。在 Java 8 中编译这样的 sub-interface 时,将生成一个桥接方法,该方法不会为 Java 7 目标生成,因为它甚至不适用于 Java 7 目标。

现在为接口生成桥接方法的原因是您通常拥有比接口更多的实现类,因此在接口中拥有default 桥接方法可以避免您将桥接方法添加到每个实现中。此外,如果只有一个 abstract 方法并且没有要实现的桥接方法,它会使 lambda 类的生成更加容易。

interface 层次结构需要桥接方法但不提供defaults 时,编译器必须使用LambdaMetafactory.altMetafactory 生成代码,而不是LambdaMetafactory.metafactory 指定所需的每个桥接方法。

【讨论】:

    【解决方案2】:

    请原谅,但它必须在一个平行宇宙中,Javadoc 措辞充分解释了这种行为:https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getDeclaredMethods--。 “所有声明的方法”的数组结果是“用户声明的所有方法以及 StackOverflow 上解释的一些底层实现细节”的数组。更糟糕的是,我看到一些关于注解的奇怪之处:我在应用注解时覆盖了一个泛型方法,getDeclaredMethods() 返回的两个 abstract&default 方法都有注解,但只有 abstract 一个具有正确的非泛型参数。所以在我看来,这个实现细节部分违背了通过注释搜索方法的目的。

    【讨论】:

      猜你喜欢
      • 2011-10-27
      • 1970-01-01
      • 2015-05-14
      • 2010-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-25
      相关资源
      最近更新 更多