【问题标题】:Why does this method reference assignment compile?为什么这个方法引用赋值编译?
【发布时间】:2017-04-20 15:04:53
【问题描述】:

我很难理解为什么以下代码可以编译:

public class MethodRefs {

    public static void main(String[] args) {
        Function<MethodRefs, String> f;

        f = MethodRefs::getValueStatic;

        f = MethodRefs::getValue;
    }

    public static String getValueStatic(MethodRefs smt) {
        return smt.getValue();
    }

    public String getValue() {
        return "4";
    }

}

我知道为什么第一个赋值是有效的 - getValueStatic 显然匹配指定的 Function 类型(它接受一个 MethodRefs 对象并返回一个 String),但第二个让我感到困惑 - @987654329 @ 方法不接受任何参数,为什么分配给f 仍然有效?

【问题讨论】:

标签: java java-8


【解决方案1】:

第二个

f = MethodRefs::getValue;

相同
f = (MethodRefs m) -> m.getValue();

对于非静态方法,总是有一个隐式参数,在被调用者中表示为this

注意:字节码级别的实现略有不同,但做的事情是一样的。

【讨论】:

  • 请注意,隐式参数可以显式化(从 Java 8 开始):public String getValue(MethodRefs this) 是合法的,并且与 public String getValue() 相同。
  • @Pokechu22 我不知道。该构造有名称吗?
  • @immibis: the spec (§8.4.1) 据我所知,它称之为“接收器参数”。
【解决方案2】:

让我们稍微充实一下:

import java.util.function.Function;

public class MethodRefs {

  public static void main(String[] args) {
    Function<MethodRefs, String> f;


    final MethodRefs ref = new MethodRefs();

    f = MethodRefs::getValueStatic;
    f.apply(ref);
    //is equivalent to 
    MethodRefs.getValueStatic(ref);

    f = MethodRefs::getValue;
    f.apply(ref);
    //is now equivalent to 
    ref.getValue();
  }

  public static String getValueStatic(MethodRefs smt) {
    return smt.getValue();
  }

  public String getValue() {
    return "4";
  }
}

【讨论】:

    【解决方案3】:

    非静态方法本质上将其this 引用作为一种特殊的参数。通常,该参数以特殊方式编写(在方法名称之前,而不是在其之后的括号内),但概念是相同的。 getValue 方法接受一个MethodRefs 对象(它的this)并返回一个字符串,因此它与Function&lt;MethodRefs, String&gt; 接口兼容。

    【讨论】:

      【解决方案4】:

      在 Java 教程中解释了有 4 种不同类型的方法引用:

      1. 引用静态方法
      2. 对特定对象的实例方法的引用
      3. reference to an instance method of an arbitrary object of a particular type
      4. 对构造函数的引用

      您的情况是#3,这意味着当您有MethodRef 的实例时,即ref,在您的函数f 上调用apply 将等效于String s = ref.getValue()

      【讨论】:

        【解决方案5】:

        对于非静态方法,this 的类型被隐式认为是第一个参数类型。由于它的类型为MethodRefs,因此类型已检出。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-04-26
          • 1970-01-01
          • 1970-01-01
          • 2020-12-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多