为什么这个方法引用赋值编译?

cod*_*box 44 java java-8

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

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";
    }

}
Run Code Online (Sandbox Code Playgroud)

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

Pet*_*rey 50

第二个

f = MethodRefs::getValue;
Run Code Online (Sandbox Code Playgroud)

是相同的

f = (MethodRefs m) -> m.getValue();
Run Code Online (Sandbox Code Playgroud)

对于非静态方法,始终存在隐式参数,该参数this在被调用者中表示.

注意:字节代码级别的实现略有不同,但它的功能相同.

  • 请注意,隐式参数可以是显式的(从Java 8开始):`public String getValue(MethodRefs this)`是合法的,与`public String getValue()`相同. (24认同)
  • @immibis:[规范](http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.1)(§8.4.1)称之为"接收器参数"据我所知. (5认同)

Wyz*_*a-- 9

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


And*_*eas 9

让我们充实一点:

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";
  }
}
Run Code Online (Sandbox Code Playgroud)


Fed*_*ner 6

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

  1. 引用静态方法
  2. 引用特定对象的实例方法
  3. 引用特定类型的任意对象的实例方法
  4. 对构造函数的引用

你的情况是#3,这意味着当你有一个MethodRefie 的实例时ref,调用apply你的函数f将相当于String s = ref.getValue().


Car*_*ate 5

对于非静态方法,类型this被隐式地视为第一个参数类型.由于它是类型MethodRefs,类型检查.