Java 8方法引用:在编译时验证方法

ele*_*ype 15 java java-8

我想使用Java 8 的新方法引用在编译时提供一些代码的更多验证.

假设我有一个validateMethod方法需要一个参数:要验证的"方法".例如 :

validateMethod(foo, "methodA");
Run Code Online (Sandbox Code Playgroud)

这里,该方法将在运行时验证foo#methodA()存在.

使用方法引用,我希望能够:

validateMethod(foo::methodA);
Run Code Online (Sandbox Code Playgroud)

因此,该方法的存在将在编译时验证.

问题是似乎必须将方法引用分配给功能接口.例如,这个:

Object dummy = foo::methodA;
Run Code Online (Sandbox Code Playgroud)

生成错误:" 此表达式的目标类型必须是功能接口 ".

如果我创建一个与该methodA方法具有兼容签名的功能接口,它可以工作:

@FunctionalInterface
public interface MyFunctionalInterface
{
    public String run();
}
MyFunctionalInterface dummy = foo::methodA;
Run Code Online (Sandbox Code Playgroud)

现在存在的foo#methodA()是在编译时验证的,这就是我想要的!

但...

假设validateMethod不知道它必须验证的方法的签名.那么它仍然可以实现吗?

让我们假装我们不关心歧义和重载方法.在Java 8中是否可以实现某种方法来触发任何方法引用的验证?

例如 :

public class Foo
{
    public String methodA()
    {
        return "methodA";
    }

    public String methodB(String str)
    {
        return "methodB";
    }

    public String methodC(String str, int nbr)
    {
        return "methodC";
    }
}

Foo foo = new Foo();
validateMethod(foo::methodA); // Compile
validateMethod(foo::methodB); // Compile
validateMethod(foo::methodC); // Compile
validateMethod(foo::methodD); // Error!
Run Code Online (Sandbox Code Playgroud)

是否可以以validateMethod接受任何方法引用的方式实现,因此该方法的存在将在编译时验证?

我试过了 :

public void validateMethod(Object obj){}
Run Code Online (Sandbox Code Playgroud)

但它不起作用:" 此表达式的目标类型必须是功能接口 "

这可行:

@FunctionalInterface
public interface MyFunctionalInterface
{
    public String run();
}
public void validateMethod(MyFunctionalInterface param){}
Run Code Online (Sandbox Code Playgroud)

但仅适用methodAFoo类,因为它的签名(无参数)与功能接口的方法签名兼容!

是否有可能以MyFunctionalInterface这样的方式实现功能接口:任何方法引用都是有效参数,因此将在编译时验证?

您认为在编译时验证方法是否存在的任何其他方法?

Ale*_*lev 13

你似乎试图使用方法引用,它实际上是lambda表达式简写,作为方法文字,它是方法语法引用(很像Foo.class是对Foo类实例的语法引用).这两个是不一样的,这就是你遇到阻抗的原因.你尝试的是滥用javac编译器完全拒绝的语言功能.

不幸的是,Java中没有方法文字,所以你必须通过其他方法来描述方法,例如Reflection,MethodHandles.Lookup等.我认为很容易想出这种反射检查器,甚至构建注释处理器以在编译时检查给定方法的存在.