java – 具有不同arities的重载方法的无效方法引用

前端之家收集整理的这篇文章主要介绍了java – 具有不同arities的重载方法的无效方法引用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
尝试编译表达式Comparator.comparing(String :: toLowerCase)时,Java编译器返回错误.有关更多信息,请参阅以下问题:

Why Comparator.comparing doesn’t work with String::toLowerCase method reference?

我试图尽可能地减少这个问题.特别是,我已经删除了几乎所有依赖项到其他类. main方法包含两个方法调用.第一个语句编译时没有错误,而第二个语句产生错误.

interface Fun<T,R> { R apply(T t); }

public final class Foo {
    public static void main(String... args) {
        invoke(Foo::bar); // OK
        invoke(Foo::baz); // ERROR
    }
    private static <T,U> void invoke(Fun<T,U> f) { }
    private String bar() { return null; }
    private String baz() { return null; }
    private String baz(Integer i,Integer j) { return null; }
}

这很奇怪,因为第二个baz方法不应该适用于这种情况,因为参数的数量不匹配.我看过JLS8(15.13).但是,没有任何帮助,因为方法引用的规则非常复杂.

问:为什么第二种情况会出现编译错误?根据JLS真的会出现编译错误吗?根据对另一个问题的一些评论,Netbeans中没有编译错误.

作为参考,我使用的是JDK8版本1.8.0-b132.如果在命令行上编译程序,编译器将显示以下错误消息:

$/opt/jdk8/bin/javac Foo.java
Foo.java:6: error: incompatible types: cannot infer type-variable(s) T,U
        invoke(Foo::baz); // ERROR
              ^
    (argument mismatch; invalid method reference
      no suitable method found for baz(Object)
          method Foo.baz() is not applicable
            (actual and formal argument lists differ in length)
          method Foo.baz(Integer,Integer) is not applicable
            (actual and formal argument lists differ in length))
  where T,U are type-variables:
    T extends Object declared in method <T,U>invoke(Fun<T,U>)
    U extends Object declared in method <T,U>)
Foo.java:6: error: invalid method reference
        invoke(Foo::baz); // ERROR
               ^
  non-static method baz() cannot be referenced from a static context
2 errors

解决方法

JLS8 (15.13)令人困惑,但它确实显示了类似于你的例子,说明他们在搜索中的含糊不清是无法解决的.

对于你的例子,Intellij说invoke(Foo :: baz);是一个循环推理,我认为它更多地与调用需要推断类型以及Foo :: baz的组合有关.

这可以通过为调用函数赋予类型来解决,类似于JSL(15.13.1示例)

The search is smart enough to ignore ambiguities in which all the applicable methods (from both searches) are instance methods:

FOO< FOO,字符串>调用(FOO ::巴兹); – 相当于,我想使用Foo的void方法返回一个String aka String baz()

interface Fun<T,R> { R apply(T t); }
interface Fun2<T,U,R> { R apply(T t,U u); }

public final class Foo {
    public static void main(String... args) {
        invoke(Foo::bar); // OK
        Foo.<Foo,String>invoke(Foo::baz); // NO ERROR
        Fun2<Foo,Integer,String> f2 = Foo::baz; // Overloaded method baz
    }
    private static <T,U> f) { }
    private String bar() { return null; }
    private String baz() { return null; }
    private String baz(Integer i) { return null; } 
}

我同意你的看法,baz(Integer i)不是一个有效的参数,无需调用它就可以将其设置为静态或来自Foo的实例.我想如果方法过载并且它试图推断出类型,搜索算法就会退出.因为它只使用一个方法签名.

猜你在找的Java相关文章