当前位置: 首页 > 知识库问答 >
问题:

Java 找不到使用双冒号运算符的正确重载方法

卢健
2023-03-14

当使用双冒号操作符引用重载的方法时,Java似乎不能确定要使用的正确方法。考虑这个例子:

public class A {
    private void setter(final Number value) { }
    private void setter(final Optional<Number> value) { }
    private void setter2(final Optional<Number> value) { }

    private <T> void useSetter(final Consumer<Optional<T>> a) { }

    private void callMethod() {
        useSetter(this::setter); // Error here
        useSetter(this::setter2);
    }
}

useSetter 的第一次调用不会编译,并给出以下错误:

Cannot infer type argument(s) for <T> useSetter(Consumer<Optional<T>>)
The type A does not define setter(Optional<Object>) that is applicable here

然而,第二个调用编译得很好,这意味着问题在于setter的重载。只有一个<code>setter</code>重载是适用的,所以我不明白为什么这不起作用。

可以通过使用指定参数类型的lambda来解决这个问题,但这要详细得多。

useSetter((final Optional<Number> v) -> setter(v));

有更好的方法来处理这种情况吗?还是我一直在解决这个奇怪的怪癖?

共有1个答案

陈昂熙
2023-03-14

编译私有代码的捕获

Main.java:12: error: incompatible types: cannot infer type-variable(s) T
        useSetter(this::setter); // Error here
                 ^
    (argument mismatch; invalid method reference
      no suitable method found for setter(Optional<Object>)
          method A.setter(Number) is not applicable
            (argument mismatch; Optional<Object> cannot be converted to Number)
          method A.setter(Optional<Number>) is not applicable
            (argument mismatch; Optional<Object> cannot be converted to Optional<Number>))
  where T is a type-variable:
    T extends Object declared in method <T>useSetter(Consumer<Optional<T>>)

一种解决方案是使用私有创建绑定

class A<T> {
    private void setter(final Number value) { }
    private <T> void setter(final Optional<? super T> value) { }
    private void setter2(final Optional<Number> value) { }

    private <T> void useSetter(final Consumer<Optional<T>> a) { }

    private void callMethod() {
        useSetter(this::setter); // no more error
        useSetter(this::setter2);
    }

    public static void main(String [] args){

    }
}

class B {
    private void setter(final Number value) { }
    private void setter(final Optional<? super Number> value) { }
    private void setter2(final Optional<Number> value) { }

    private <T> void useSetter(final Consumer<Optional<T>> a) { }

    private void callMethod() {
        useSetter(this::setter); // no more error
        useSetter(this::setter2);
    }

    public static void main(String [] args){

    }
}

你可以在这里查看ideone。

这两个选项都不是完美的,因为它会通过允许<code>选项为代码引入一些可替换性

 类似资料:
  • 刚刚在java中尝试了一些东西,发现了以下问题。 以下是我的代码。 父接口: 子接口: 实施1: 实施2: 主要方法: 我不确定我做错了什么,我在本地机器中安装了JDK 13并使用IntelliJ 2019.3和JDK 11。我检查了IntelliJ是否支持JDK 13 谢谢 错误更新我在那里留下了一个分号,删除了它,请再次检查。

  • 问题内容: 我正在探索Java 8源代码,发现代码的这一特殊部分非常令人惊讶: 是类似方法指针的东西吗?普通方法如何转换为? 问题答案: 通常,可以使用以下方法调用该方法: 仅调用就需要很多语法。那就是lambda表达式起作用的地方。从Java 8开始,它允许以更短的方式执行相同的操作: 这是如何运作的?Java编译器“检测”你要实现一个接受两个ints并返回一个的方法int。这等效于接口的唯一方

  • 我在探索Java 8的源代码时,发现代码的这一部分非常令人惊讶: 是否类似于方法指针?普通的方法如何转换为?

  • 问题内容: 如您所知,有一个功能快捷方式的建议,因此您可以编写: 它将在es5中像这样工作: 我的问题是:是否可以通过这种方式传递参数? 我的意思是用上述快捷方式编写此代码的方法: 这是React中很常见的模式,因此最好将其缩短一点。 问题答案: 否。bind运算符(规范建议)有两种形式: 方法提取 “虚拟方法”调用 obj::function(…) ≡ function.call(obj, …)

  • 关于使用问号的两个问题"?"和冒号":"打印函数括号内的运算符:它们是做什么的?还有,有人知道它们的标准术语吗?或者我在哪里可以找到更多关于它们使用的信息?我读过它们类似于“if”“其他”语句。

  • 问题内容: 我有这样的字符串 我想用冒号作为分隔符,而不是双冒号。所需结果: 我正在尝试: 但我得到了错误的结果。 在此期间,我逃避,用 问题答案: 您可以继续讨论。这使用两个否定的环视(回溯和回溯),它们断言有效匹配只有一个冒号,在它之前或之后没有冒号。 解释模式: 这两种环视都是必需的,因为如果只有后向,则正则表达式引擎将匹配其中的第一个冒号(因为前一个字符不是冒号),如果只有前瞻,则第二个冒