是否有可能(如何)在运行时获取方法引用的名称Java?

Is it possible (how) to get the name of a method reference at Runtime Java?

我最近一直在使用很多方法引用和 lambda,并且想在 运行 时知道我是否可以打印以筛选 lambda 的来源,即它的名称,只是出于调试原因。我认为通过在 getName() 中调用 getClass() 可以使用反射,但我找不到找到原始源引用名称的方法。

我有一个函数式界面,例如:

@FunctionalInterface
public interface FooInterface {
    // function etc etc irrelevant
    public void method();

    public default String getName() {
        // returns the name of the method reference which this is used to define
    }
}

然后假设我想测试 运行 界面,并将功能界面的源代码打印到屏幕上。

public static void doStuff(FooInterface f) {
    // prints the lambda name that is used to create f
    System.out.println(f.getName());

    // runs the method itself
    f.method();
}

所以如果我这样做:

doStuff(Foo::aMethodReference);

它应该在屏幕上打印如下内容:"aMethodReference",这样我就可以知道,在 运行 时间,哪些方法正在 运行,以什么顺序等

考虑到 lambda 不是完全对象,我很怀疑这是否可行,但是嘿,我认为可能有解决方法。此外,eclipse 调试工具只是说它是一个 lambda,没有任何其他信息,lambda 是否保留任何这些信息?还是在运行时全部丢失?

干杯。 (如果有什么不同的话,我正在使用 JDK 11)

正如您所说,您只需要将其用于调试目的,这里有一个技巧(即肮脏的技巧)可以让您做您想做的事。

首先你的功能界面必须是Serializable:

@FunctionalInterface
public interface FooInterface extends Serializable {

    void method();
}

现在,您可以使用此未记录、依赖于内部实现且风险极大的代码来打印有关方法引用的一些信息针对您的FooInterface功能界面:

@FunctionalInterface
public interface FooInterface extends Serializable {

    void method();

    default String getName() {
        try {
            Method writeReplace = this.getClass().getDeclaredMethod("writeReplace");
            writeReplace.setAccessible(true);
            SerializedLambda sl = (SerializedLambda) writeReplace.invoke(this);
            return sl.getImplClass() + "::" + sl.getImplMethodName();
        } catch (Exception e) {
            return null;
        }
    }
}

调用此方法时:

doStuff(Foo::aMethodReference);

您将看到以下输出:

package/to/the/class/Foo::aMethodReference

注意 1:我在 this article by Peter Lawrey 中看到过这种方法。

注意 2:我已经用 openjdk version "11" 2018-09-25java version "1.8.0_192".

测试过这个