加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-15 00:39:01 所属栏目:Java 来源:网络整理
导读:尝试编译表达式Comparator.comparing(String :: toLowerCase)时,Java编译器返回错误.有关更多信息,请参阅以下问题: Why Comparator.comparing doesn’t work with String::toLowerCase method reference? 我试图尽可能地减少这个问题.特别是,我已经删除了几
尝试编译表达式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的实例.我想如果方法过载并且它试图推断出类型,搜索算法就会退出.因为它只使用一个方法签名.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读