为什么Java 8引入了一个新的方法引用"::"运算符?



在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;
  ...
}

您可以看到,addableViaMethodReference现在充当AddableUtil::addThemUp的别名。因此addableViaMethodReference()将执行与AddableUtil.addThemUp()相同的操作并返回相同的值。

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

方法执行

AddableUtil.addThemUp();

方法参考

AddableUtil.addThemUp;

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

以下代码在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.addThemUp是引用了公共IntBinaryOperator字段,还是试图创建方法引用。

是的,这有点做作。但是在编程语言语法中不能允许出现边缘情况。

字段和方法有单独的名称空间,因此方法名称和字段名称之间可能存在歧义(这可能需要更多的规则来消除歧义)。对于"重用一些现有语法"方法来说,这无疑是一个大问题(BTW被认为是一个候选者,还有许多其他可能性。)

但是,我想扭转这个问题:"重载"这样的现有语法真的是个好主意吗?(您的问题假设了这一点,但这是一个巨大的假设。)"调用方法m/read字段f"one_answers"按名称引用方法m/field f"之间有很大的区别。这两种表达方式看起来不应该不同吗?重用现有语法来表示完全不同的东西有什么好处?

此外,您建议的方法还存在可扩展性问题:如果不发明一种新的语法,我们将来就永远无法进行字段引用,而这种语法将与方法引用的语法不同。虽然字段引用不是lambda的必备项,但永远无法在这里完成任务将是一个很大的缺点。

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

也许他们这样做是为了让C++程序员在Java中更受欢迎?/*在我看来(作为一个怀疑论者使用的危险词),运算符:在静态方法上使用更自然,因为它是C++*/中的范围解析运算符

最新更新