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

时间:2015-03-11 09:21:15

标签: java lambda java-8 java-stream

对于给定外部类实例的内部类,是否存在等价于StaticClass::new的东西?

编辑:

即。如果我有

class Outer {
    class Inner {
    }
}

我可以用旧Java做Outer o = new Outer(); Inner i = o.new Inner()。如何将o.new Inner()表示为函数引用。

3 个答案:

答案 0 :(得分:10)

根据Oracle tutorials,有四种方法参考:

  • 参考静态方法
    • ContainingClass::staticMethodName
  • 引用特定对象的实例方法
    • containingObject::instanceMethodName
  • 引用特定类型的任意对象的实例方法
    • ContainingType::methodName
  • 对构造函数的引用
    • ClassName::new

未列出对本地/嵌套类的引用,因此我认为它不受支持。

您可以使用java.util.function.Supplier触发lambda的使用,以获取嵌套类的实例:

Outer outer = new Outer();
Supplier<Outer.Inner> supplier = () -> outer.new Inner();

答案 1 :(得分:6)

JLS中的Chapter 15.13. Method Reference Expressions包含了一个有点神秘的声明:

  

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

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

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

但是JLS没有提到任何替代方案,因此必须假设以this之外的任何其他形式提供封闭实例是不可能的。

答案 2 :(得分: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(...)