为什么 Java 8 为方法引用引入了新的“::”运算符?

2022-09-01 22:04:25

在 Java 8 中,方法引用是使用运算符完成的。::

例如

// Class that provides the functionality via it's static method
public class AddableUtil {
  public static int addThemUp(int i1, int i2){
    return i1+i2;
  }
}

// Test class
public class AddableTest {
  // Lambda expression using static method on a separate class
  IAddable addableViaMethodReference = AddableUtil::addThemUp;
  ...
}

您可以看到,now 就像 是 的别名。因此将执行与相同的操作并返回相同的值。addableViaMethodReferenceAddableUtil::addThemUpaddableViaMethodReference()AddableUtil.addThemUp()

为什么他们选择引入新的运营商而不是使用现有的运营商?我的意思是,当函数名称以 结尾时执行函数,并在没有尾随时返回函数引用。()()

方法执行

AddableUtil.addThemUp();

方法参考

AddableUtil.addThemUp;

这难道不是更简单和直观吗?AFAIK目前(Java 7)不用于任何其他目的,并引发编译错误。为什么不利用这个机会,而不是创建一个全新的运营商呢?AddableUtil.addThemUp


答案 1

下面的代码段在 Java 8 中编译良好,但是如果没有新的运算符,就会变得模棱两可:

import java.util.function.IntBinaryOperator;

public class A {

  public static IntBinaryOperator addThemUp;

  public static int addThemUp(int i1, int i2) {
    return i1 + i2;
  }

  public static void main(String[] args) throws Exception {
    IntBinaryOperator operator = A::addThemUp;
  }
}

目前尚不清楚是引用公共字段还是尝试创建方法引用。A.addThemUpIntBinaryOperator

是的,这有点人为的。但是,您不能在编程语言语法中允许边缘情况


答案 2

字段和方法具有单独的命名空间,因此方法名称和字段名称之间可能存在歧义(这可能需要更多规则来消除歧义)。对于“重用一些现有语法”方法来说,这绝对是一个大问题(顺便说一句,这种方法被认为是候选者,其他一些可能性也是如此。

但是,我会把问题转过来:“重载”像这样的现有语法真的是一个好主意吗?(你的问题假设了这一点,但这是一个巨大的假设。“调用方法 m / 读取字段 f”和“按名称引用方法 m / 字段 f”之间有很大的区别。这两种表达方式难道不应该看起来不同吗?重用现有语法来表示完全不同的东西有什么好处?

此外,您建议的方法存在一个可伸缩性问题:如果不发明一种新的语法,我们将来永远无法进行字段引用,这将与方法引用的语法不同。虽然字段引用不是 lambda 的必备条件,但永远无法在这里完成工作将是一个很大的减号。

这些只是促成这一决定的各种考虑因素中的一小部分。事后看来,我仍然认为我们在这里做出了正确的决定。


推荐