MethodReference 表达式的归约过程

Reduction procedure for MethodReference Expressions

考虑 JLS 的以下文章,该文章描述了类型推断过程中 MethodReference 表达式的缩减过程:

A constraint formula of the form ‹MethodReference → T›, where T mentions at least one inference variable, is reduced as follows:

...

Otherwise, if the method reference is exact (§15.13.1), then let P1, ..., Pn be the parameter types of the function type of T, and let F1, ..., Fk be the parameter types of the potentially applicable method. The constraint reduces to a new set of constraints, as follows:

– In the special case where n = k+1, the parameter of type P1 is to act as the target reference of the invocation. The method reference expression necessarily has the form ReferenceType :: [TypeArguments] Identifier. The constraint reduces to ‹P1 <: ReferenceType› and, for all i (2 ≤ i ≤ n), ‹Pi → Fi-1›.

In all other cases, n = k, and the constraint reduces to, for all i (1 ≤ i ≤ n), ‹Pi → Fi›.

在这里,我想知道一些示例案例,说明如何在子句中假设和安装以下内容:

例如-以下是我根据解释提出的问题:

FunctionType<P1,P2 ... Pn> funType = ClassCls::MethodRef;
...
class ClassCls {
...
 public static <F1, ..., Fk> RetType potentiallyApplicbMethod(...){}
}
  • 现在我们以 n=k+1 为例
    • 为什么 FunctionType 的参数数量会比 potentiallyApplicbMethod 多?
    • 为什么是P1 is to act as the target reference of the invocation?我猜这里 P1 被假定为 potentiallyApplicbMethod?
    • 的 return 类型 (RetType)
  • 对于 n=k 的情况
    • 我假设这是在 FunctionType 中指定的所有类型(可能包括也可能不包括 return 类型)与为 potentiallyApplicbMethod?

Why will FunctionType have more number of arguments than the potentiallyApplicbMethod?

有不同形式的方法引用。其中一种形式是 ReferenceType::InstanceMethod,或者如 Java Tutorials 所说,“对特定类型的任意对象的实例方法的引用”。

示例:

public class Main {

    public static void main(String[] args) {
        // this is a "reference to an instance method of an arbitrary object of a particular type"
        BiConsumer<Main, String> bar = Main::foo;
    }

    private <T> void foo(T t) {

    }
}

很明显,BiConsumer的函数类型有2个参数,而foo只有一个。函数类型的额外第一个参数是需要的,因为你需要一个实例来调用foo,而我们没有在方法引用中指定那个实例Main::foobar.accept(new Main(), "foo") 与调用 new Main().foo("foo") 相同。这就是 JLS 中“目标引用”的含义——它是您调用方法的对象。它与 return 类型无关。

现在你应该也能明白为什么 JLS 说 n=k+1 情况下的方法引用必须是 ReferenceType :: [TypeArguments] Identifier 的形式,而不是 Primary :: [TypeArguments] Identifier.

for the case when n=k I assume this is given as when all types specified in FunctionType matches exactly with all the types specified for potentiallyApplicbMethod?

不是,这个案例只是参考了其他几种方法:

  • 引用静态方法
  • 引用特定对象的实例方法
  • 对class或数组
  • 的构造函数的引用