10

我有以下代码:

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

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

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

他是对的吗?谢谢。

4

3 回答 3

3

您的朋友是对的,但这当然取决于使用情况。

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

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

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

于 2013-05-17T05:33:25.420 回答
1

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

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

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

于 2013-05-17T10:55:33.373 回答
0

我构建了一个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
于 2013-05-17T06:09:53.587 回答