方法引用本地类构造函数

And*_*niy 5 java lambda java-8 method-reference

关于本地类构造函数的方法引用,有几个类似的问题,但我想稍微澄清一下其他的东西.请考虑以下代码:

static Callable gen(int i) {
    class X {
        int x = i;
        public String toString() { return "" + x; }
    }
    return X::new;
}

...

System.out.println(gen(0).call()); 
System.out.println(gen(1).call());
Run Code Online (Sandbox Code Playgroud)

显然这将打印输出

0
1
Run Code Online (Sandbox Code Playgroud)

事实证明,X该类具有表单的构造函数...$X(int)(您可以通过它找到它X.class.getDeclaredConstructors()).

但有趣的是,返回的lambdas(或方法引用)并不是对构造函数的简单引用...$X(int),例如,Integer::new.它们在内部...$X(int)使用预定义的参数(01)调用此构造函数.

所以,我不确定,但看起来这种方法参考在JLS中没有精确描述.除了本地类的这种情况之外,没有其他方法可以生成这种lambda(使用预定义的构造函数参数).谁能帮忙澄清一下?

确切地说:

  • JLS在哪里描述了这种方法参考?

  • 是否有任何其他方法来创建此类方法引用具有预定义参数的任意类构造函数?

Hol*_*ger 3

您过于关注不相关的低级细节。在字节码级别,可能有一个接受int参数的构造函数,但在语言级别,您没有\xe2\x80\x99t指定显式构造函数,因此,将有一个不带任何参数的默认构造函数,与任何其他构造函数一样班级。

\n\n

当您编写 Java\xc2\xa08 之前的代码时,这一点应该会变得很清楚:

\n\n
static Callable<Object> gen(int i) {\n    class X {\n        int x = i;\n        public String toString() { return "" + x; }\n    }\n    X x=new X();\n    \xe2\x80\xa6\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以X通过其默认构造函数进行实例化,不带任何参数。您的本地类捕获的值i,但它如何在低级别上执行此操作,即X\xe2\x80\x99 构造函数具有合成int参数,并且表达式将向其new传递 的值,是实现细节。i

\n\n

您甚至可以添加显式构造函数

\n\n
        X() {}\n
Run Code Online (Sandbox Code Playgroud)\n\n

不改变任何东西。

\n\n

显然,您也可以在此处将表达式new X()写入 lambda 表达式内,因为表达式在放置在 lambda 表达式内时不会改变其语义:

\n\n
    return () -> new X();\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者用\xe2\x80\x99的简写形式,方法参考

\n\n
    return X::new;\n
Run Code Online (Sandbox Code Playgroud)\n\n

它没有什么特别的,如果您忘记了分散注意力的低级细节,即使不参考规范,该行为也是可以理解的。X可以捕获任意数量的局部变量,构造函数\xe2\x80\x99的参数数量不会改变(在语言级别)。

\n