【问题标题】:Constructor method reference for (non-static) inner class?(非静态)内部类的构造方法参考?
【发布时间】:2015-03-11 09:21:15
【问题描述】:

对于给定外部类实例的内部类,StaticClass::new 是否有等价物?

编辑:

即如果我有

class Outer {
    class Inner {
    }
}

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

【问题讨论】:

  • 您能否添加一些代码,即该类的具体定义位置以及您想在何处使用它?
  • 有趣的是,在JLS on method references 的示例部分中,有一个示例:Outer.Inner::new 但这不会编译...它们可能意味着Outer.StaticNested::new...
  • 不是方法参考,但你可以使用像() -> outer.new Inner()这样的lambda
  • @assylias: Outer.Inner::new 如果你在 inside Outer,即如果Outer 的实例在范围内,则确实有效。当然,你可以只写Inner::new 然后……

标签: java lambda java-8 java-stream


【解决方案1】:

根据Oracle tutorials,有四种方法引用:

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

没有列出对本地/嵌套类的引用,所以我认为它不受支持。

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

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

【讨论】:

    【解决方案2】:

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

    新内部类实例 (§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() 的原因几乎相同。 :)
    【解决方案3】:

    对于静态嵌套类,你可以使用外部类引用它-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 -&gt; a.new B(x) 转换为 A.B::new,但这不会编译,因为 B 不是静态的 - 它不属于 A 类,而是属于 A 类的实例。所以回答你的问题 - 我认为这是不可能的,你必须使用outerInstanceName.new InnerClass(...)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-21
      • 2020-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-23
      相关资源
      最近更新 更多