java - 对本地类构造函数的方法引用

标签 java lambda java-8 method-reference

关于对本地类构造函数的方法引用,SO 上有几个类似的问题,但我想稍微澄清一下其他事情。考虑以下代码:

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());

显然这将打印输出

0
1

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

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

所以,我不确定,但看起来 JLS 中没有准确描述这种方法引用。除了本地类的这种情况之外,没有其他方法可以生成这种 lambdas(具有预定义的构造函数参数)。谁能帮忙解释一下?

准确地说:

  • JLS中哪里有这样的方法引用描述?

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

最佳答案

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

当您编写 Java 8 之前的代码时,这应该变得清楚:

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

您通过其默认构造函数实例化 X,不接受任何参数。您的本地类捕获 i 的值,但它是如何在低级别上实现的,即 X 的构造函数具有合成的 int 参数和new 表达式会将i 的值传递给它,是一个实现细节。

您甚至可以添加一个显式构造函数作为

        X() {}

不改变任何东西。

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

    return () -> new X();

或者使用它的简写形式,方法引用

    return X::new;

它没有什么特别之处,如果您忘记了令人分心的底层细节,即使不引用规范,该行为也是可以理解的。 X 可以捕获任意数量的局部变量,构造函数的参数数量不会改变(在语言级别)。

关于java - 对本地类构造函数的方法引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34863650/

相关文章:

java - 使用 JTable java 将数据添加到数据库中两次

java - Kotlin 中 getOrElseReturn 的可能性

Java 8 兼容性问题 : How to convert Object array to Subtype List in Java 8?

json - 如何在 ReSTLet 中注册 Jackson Jdk8 模块

java - 将 JFrame 居中?

Java:读取相对较大的 txt 文件并存储其数据的最有效方法是什么?

java - 如何在库本身中使用库生成的类

ruby-on-rails - 如何将属性作为参数传递给在类上调用的方法?

c# - 获取 MethodCallExpression 的参数值

c# - Lambda 解释和它是什么以及一个很好的例子