【问题标题】:Calling method reference using lambda (:: operator)使用 lambda (:: operator) 调用方法引用
【发布时间】:2021-12-13 20:00:03
【问题描述】:

我见过一些方法如下图:

这样调用:

private static void addCustomerTransaction() {
  customerInput((bank, branchName, customerName, transaction) ->
      bank.addCustomerTransaction(branchName, customerName, transaction));
}

private static void addCustomer() {
  customerInput((bank, branchName, customerName, transaction) ->
      bank.addCustomer(branchName, customerName, transaction));
}


或使用方法引用:

private static void addCustomerTransaction() {
  customerInput(Bank::addCustomerTransaction);
}

private static void addCustomer() {
  customerInput(Bank::addCustomer);
}

我读过这样的代码:当调用addCustomerTransaction() 方法时,它通过传递Bank 类的addCustomer 方法来调用customerInput 方法。但这似乎是一个递归调用。那么,这是什么意思,你能举一个简单的例子吗?

提前致谢。

【问题讨论】:

  • customerInput(Bank::addCustomerTransaction) 基本上被翻译成(bank, branchName, customerName, transaction) -> bank.addCustomerTransaction(branchName, customerName, transaction)),因为它们具有相同的签名。问题是第一个参数bank 是银行实例,addCustomerTransaction(String branchName, String customerName, Transaction transcation)(猜测参数类型)实际上有一个隐式的第一个this 参数,即银行。所以这个方法不同于静态的addCustomerTransaction()
  • 这里还有一个相关主题的快速查找,希望能解释 Java 中不同风格的 lambda 和方法引用:geeksforgeeks.org/method-references-in-java-with-examples
  • @Thomas 非常感谢,但无法完全理解。也许我的例子不是一个合适的例子。你能用一个合适的例子作为答案来解释吗?
  • @M.Prokhorov 看起来很有用,非常感谢。

标签: java class lambda stream method-reference


【解决方案1】:

不,这不是递归调用,因为Bank::addCustomerTransaction 不会引用private static void addCustomerTransaction(),而是引用具有相同名称和合适签名的方法。我将提供一个简单的答案,但请在这方面寻找适当的教程以获取详细信息。

让我们假设customerInput() 的参数是一个具有如下方法的接口:

void takeInput(Bank bank, String branchName, String customerName, Transaction transaction);

现在您可以传递与此签名匹配的任何方法引用,并且适用于 Java 用于普通方法调用的相同方法解析规则,即如果您有 2 个方法 void foo(int x)void foo(long x) 以及一个调用 foo(2) 编译器将需要确定您是要调用第一种方法还是第二种方法(这里将选择第一种方法,因为1int 文字)。

有了这些规则,编译器如何在你的情况下选择方法?

假设我们有以下类:

class Bank {
   void addCustomerTransaction(String branchName, String customerName, Transaction transaction) { ... }

   static void addCustomerTransaction() {
     customerInput(Bank::addCustomerTransaction);
   }
}

为什么这不是递归调用?

因为void addCustomerTransaction() 根本不匹配void takeInput(Bank, String, String, Transaction) 所需的签名。

但是为什么实例方法void addCustomerTransaction(String, String, Transaction)匹配呢?

这是因为实例方法隐式获得了第一个参数,它是对实例的引用(即this 引用),所以编译器该方法看起来像this(在内部没有静态方法和实例方法的区别):

 void addCustomerTransaction(Bank, String, String, Transaction)

现在这与所需的签名匹配,因此可以调用该方法。

为了证明这一点,尝试添加一个具有相同签名的静态方法:

 static void addCustomerTransaction(Bank bank, String branchName, String customerName, Transaction transaction) { ... }

现在编译器无法决定是使用静态方法还是实例方法,它会告诉你。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-18
  • 1970-01-01
  • 2019-08-06
  • 1970-01-01
  • 1970-01-01
  • 2018-10-03
  • 1970-01-01
相关资源
最近更新 更多