非静态内部类的构造方法引用?

9

针对内部类,是否有类似于StaticClass::new的等效方法,可以使用外部类实例创建一个内部类对象?

编辑:

即,如果我有一个

class Outer {
    class Inner {
    }
}

我能在旧版Java中执行Outer o = new Outer(); Inner i = o.new Inner()。那么如何将o.new Inner()表示为函数引用呢?


你能添加一些代码吗?比如类的确切定义位置以及你想在哪里使用它? - tobias_k
有趣的是,在方法引用的JLS示例部分,有一个例子:Outer.Inner::new但那编译不过...也许他们的意思是Outer.StaticNested::new... - assylias
不是方法引用,但你可以使用像 () -> outer.new Inner() 这样的 lambda。 - tobias_k
2
@assylias: 如果你在 Outer 内部,也就是如果一个 Outer 的实例在作用域内,Outer.Inner::new 就会起作用。当然,你也可以直接写 Inner::new - Holger
3个回答

11
根据Oracle教程,有四种方法引用类型:
  • 静态方法引用
    • ContainingClass::staticMethodName
  • 特定对象的实例方法引用
    • containingObject::instanceMethodName
  • 特定类型任意对象的实例方法引用
    • ContainingType::methodName
  • 构造函数引用
    • ClassName::new
没有列出对局部/嵌套类的引用,因此我认为不支持。
您可以使用java.util.function.Supplier触发lambda的使用以获取嵌套类的实例:
Outer outer = new Outer();
Supplier<Outer.Inner> supplier = () -> outer.new Inner();

6

JLS中的第15.13章方法引用表达式包含了一个比较晦涩的声明:

新内部类实例(§15.9.2)的直接封闭实例是由this§8.1.3)的词法封闭实例提供的。

这基本上意味着在外部类的方法中可以使用对内部类构造函数的方法引用,就像这个例子中一样。

import java.util.function.Supplier;
class Outer
{
    public class Inner
    {
    }
    void example()
    {
        Supplier<Inner> s = Inner::new;
    }
}

但是JLS没有提到任何其他的选择,因此必须假定除了使用this之外,无法以其他形式提供封闭实例。

不错。这基本上是你只能在封闭类中执行 new Inner() 的原因。 :) - Konstantin Yovkov

0

对于静态嵌套类,您可以使用外部类来引用它 - OuterClass.NestedClass::new

public class Main {

    public static void main(String[] args) {
        int[] array = {1, 2, 3};

        Arrays.stream(array).forEach(A.B::new);
    }

}

class A {

    public A(int x) {
        System.out.println("A created, x = " + x);
    }

    public static class B {

        public B(int x) {
            System.out.println("B created, x = " + x);
        }

    }

}

对于内部类(嵌套的非静态类),您可以使用 outerInstanceName.new InnerClass(...)

public class Main {

    public static void main(String[] args) {
        int[] array = {1, 2, 3};

        A a = new A(500);

        Arrays.stream(array).forEach(x -> a.new B(x));
    }

}

public class A {

    public A(int x) {
        System.out.println("A created, x = " + x);
    }

    public class B {

        public B(int x) {
            System.out.println("B created, x = " + x);
        }

    }

}

我的IDE建议我将x -> a.new B(x)转换为A.B::new,但这不会编译,因为B不是静态的 - 它不属于类A,而是属于类A的实例。所以回答你的问题 - 我认为这是不可能的,你将不得不使用outerInstanceName.new InnerClass(...)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接