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

时间:2014-10-27 14:59:22

标签: java java-8 method-reference

在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目前(Java 7)没有任何其他目的,并抛出编译错误。为什么不利用这个机会而不是创建一个全新的运营商呢?

3 个答案:

答案 0 :(得分:33)

下面的代码在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字段还是尝试创建方法引用。

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

答案 1 :(得分:16)

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

但是,我会回答这个问题:是"重载"像这样的现有语法真的是个好主意吗? (你的问题假设了这一点,但这是一个巨大的假设。)"呼叫方法m /读取字段f"之间存在很大差异。和"按名称"表示方法m /字段f。难道这两种表达方式看起来不一样吗?重用现有语法意味着完全不同的东西有什么好处?

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

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

答案 2 :(得分:1)

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