【问题标题】:Can I instantiate an anonymous class in the constructor of outer class?我可以在外部类的构造函数中实例化一个匿名类吗?
【发布时间】:2013-05-17 18:55:33
【问题描述】:

我有以下代码:

public class Outer {
     public Interface Anony {
         public void callback();
     }

     public Outer() {
        OtherClass.foo(new Anony() {
            @Override
            public void callback() {
                ....
            }
        });
    }
}

但是我的朋友告诉我这里面有一些问题。我在Outer的构造函数中创建了一个匿名类实例,所以匿名类实例隐式引用了Outer类实例,即Outer.this。但是此时,Outer 类实例还没有完全创建。所以匿名类实例引用了一个状态不完整的对象,因此出现了问题。

他说的对吗?谢谢。

【问题讨论】:

  • Anony 是一个接口,不是类!
  • 是的,但是 new Anony() {...} 创建了一个匿名类实例。对。
  • @zEro 是的,Anony 是一个接口,但这是创建实现接口的匿名类实例的语法。实例化扩展另一个类的匿名类的实例时使用相同的语法。
  • 对对对。我需要我的咖啡! :D
  • 如果您接受答案,我的投票是给 Thihara 的。他早在我之前就给了你一个更好的解释。

标签: java


【解决方案1】:

你的朋友说得对,但当然要看用法。

问题不在于在构造函数中创建内部类。如果内部类访问外部类,就会出现问题。

这是因为任何对象都无法在构造函数中提供正常的被授权者。对象操作所需的所有变量可能尚未初始化,等等。

但是,如果将内部类放在构造函数的末尾,我看不到这个问题发生,但请记住,这是一个危险的策略,因为有人可能会修改代码,然后就该调试器了。 .

【讨论】:

    【解决方案2】:

    可以这样做,但你不应该这样做。

    这是一个反模式的示例,被称为“让this 引用从构造函数中逃逸”——将正在构造的对象的引用从构造函数中传递给另一个类。您不应该这样做的原因是,在多线程环境中,已将引用传递到的类可能会在 部分 构造中看到新对象,因此 inconsistent 状态。这可能会导致奇怪且难以发现的错误。 IBM 的 article 是众多描述它的其中之一。

    不明显的是 如何 它在这里发生:匿名类实际上是 inner 类,因此它们持有对包含类的引用(即 this 正在构造) .接收者类OtherClass 可能会在构造完成之前看到this,甚至对其采取行动。

    【讨论】:

      【解决方案3】:

      我构建了一个brainf..k 示例,展示了我能想到的所有不同可能性:

      class OtherClass
      {
        public static void foo (final Anony x)
        {
          x.callback ();
        }
      }
      
      public class Outer
      {
        public interface Anony
        {
          void callback ();
        }
      
        public class Inner implements Anony
        {
          public void callback ()
          {
            System.out.println ("Inner.callback");
          }
        }
      
        public class InnerDerived implements Anony
        {
          public void callback ()
          {
            System.out.println ("InnerDerived.callback");
          }
        }
      
        public static class StaticInner implements Anony
        {
          public void callback ()
          {
            System.out.println ("StaticInner.callback");
          }
        }
      
        public Outer ()
        {
          OtherClass.foo (new Anony ()
          {
            public void callback ()
            {
              System.out.println ("Anony.callback");
            }
          });
          OtherClass.foo (new Inner ());
          OtherClass.foo (new Inner ()
          {
            @Override
            public void callback ()
            {
              System.out.println ("Anony.Inner.callback");
            }
          });
          OtherClass.foo (new InnerDerived ());
          OtherClass.foo (new InnerDerived ()
          {
            @Override
            public void callback ()
            {
              System.out.println ("Anony.InnerDerived.callback");
            }
          });
          OtherClass.foo (new StaticInner ());
          OtherClass.foo (new StaticInner ()
          {
            @Override
            public void callback ()
            {
              System.out.println ("Anony.StaticInner.callback");
            }
          });
        }
      }
      

      预期的输出应该是:

      Anony.callback
      Inner.callback
      Anony.Inner.callback
      InnerDerived.callback
      Anony.InnerDerived.callback
      StaticInner.callback
      Anony.StaticInner.callback
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-15
        • 1970-01-01
        相关资源
        最近更新 更多