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

Java方法引用是否对第一个参数与被引用的类的类型相同的方法有特殊的处理?[复制]

薛涛
2023-03-14

我遇到了一个Java方法引用的用法,我不知道如何成功地编译和执行它。

我有以下@functioninterface

@FunctionalInterface
public interface NotifyFunction {
    void notify(NotifyService notifyService, String message, int target);
}

NotifyService是一个具有以下方法的接口:

public interface NotifyService  {
    public void notifyOne(String message, int target);
    public void notifyTwo(String message, int target);
}

public class ConsoleNotifyService implements NotifyService {

    public void notifyOne(String message, int target) {
        System.out.println("[ONE] " + message + target);
    }
    
    public void notifyTwo(String message, int target) {
        System.out.println("[TWO] " + message + target);
    }
}

我添加了一个enum,用于包含所有策略:

public enum NotifyStrategy {

    // HOW???
    ONE(NotifyService::notifyOne),
    TWO(NotifyService::notifyTwo);
    
    private final NotifyFunction notifyFunction;
    
    NotifyStrategy(NotifyFunction notifyFunction) {
        this.notifyFunction = notifyFunction;
    }
    
    public void notify(NotifyService notifyService) {
        this.notifyFunction.notify(notifyService, "TEST", new java.util.Random().nextInt());
    }
}

我不明白Java如何从NotifyService::通知一个转换为Notify函数的实例:

(1) 方法签名不匹配。(2) NotifyService::notifyOne是对接口的引用。

以下main功能正常:

public static void main(String... args) {
    NotifyStrategy.ONE.notify(new ConsoleNotifyService());
    NotifyStrategy.TWO.notify(new ConsoleNotifyService());
}

共有1个答案

能逸清
2023-03-14

根据JLS

功能接口是一个只有一个抽象方法(对象方法除外)的接口,因此代表一个单一的功能契约。

NotifyFunction只定义了一个抽象方法,因此它是一个有效的函数接口。

每个功能接口都可以通过使用lambda表达式或方法引用来实现。

我不明白Java如何从NotifyService::通知一个转换为Notify函数的实例

没有这种转换NotifyFunction参考实例方法NotifyService

这种类型的方法参考被分类为

对特定类型的任意对象的实例方法的引用

如果您对方法引用中接口的使用感到困惑,下面是另一个示例:

BiFunction<Collection<Integer>, Integer, Boolean> func =
                Collection::add;

此函数需要一个集合(任意集合)和一个要添加的项。实例方法add()将在传递给该函数的任意集合上调用,而不是在collection接口上调用。

方法签名不匹配。

对于NotifyService定义的NotifyFunctionnotifyOne()方法的抽象方法,我们有以下方法签名:

notify(NotifyService notifyService, String message, int target)
notifyOne(String message, int target)

也就是说,我们可以实现Notify函数与lambda表达式类似:

(notifyService, message, target) -> notifyService.notifyOne(message, target)

这可以归结为一个方法引用NotifyService::notifyOne

 类似资料:
  • 我想这样设置参数的类型: 当我尝试这样做时,会引发错误:NameError:名称'Tree'未定义

  • 我有一个有界泛型类,我们称之为泛型,它的参数T扩展了抽象类abstract: 泛型类: 抽象类 泛型类中T引用的类 当尝试引用方法 getMap() 时,该方法来自 T 边界内的类(并且根据抽象类定义,T 的所有可能实例都将具有该方法),我收到以下错误: 不能从静态上下文引用非静态方法getMap() 然而,任何地方都没有静态关键字。我错过了什么?? 谢谢!

  • 我刚开始使用Mockito,我正在验证某个方法应该用特定的参数调用,而所有的值类型参数(int、String、enum等)都可以验证,但引用/类类型参数似乎没有,下面是一个示例 那么,我如何将引用对象传递到我的输入方法中,并在这里将其模拟为我的内部方法的返回值呢?顺便说一句,如果我的方法只包含值类型参数,它将工作...

  • 问题内容: 为什么在同一个类中使用以下两种方法是不合法的? 我得到了 方法add(Set)与类型Test中的另一个方法具有相同的擦除add(Set)。 虽然我可以解决它,但我想知道为什么javac不喜欢这样。 我可以看到,在很多情况下,这两种方法的逻辑非常相似,可以用一个方法代替 方法,但并非总是如此。 如果你想让两个带有这些参数,这会特别令人讨厌,因为那样你就不能只更改其中一个的名称。 问题答案

  • 如何在不更改方法名称的情况下摆脱以下错误: 我的方法:

  • 这行不通,因为premiumStrings::contains可以接受任何对象,而不仅仅是字符串。可以将其替换为<代码>(字符串s)- (具体来说,问题是