我可以在外部类的构造函数中实例化一个匿名类吗?

时间:2013-05-17 05:12:59

标签: java

我有以下代码:

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

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

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

他是对的吗?感谢。

3 个答案:

答案 0 :(得分:3)

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

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

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

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

答案 1 :(得分:1)

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

这是反模式的一个例子,它被称为“让this引用从构造函数中逃脱” - 将构造对象的引用传递给构造函数中的另一个类。你不应该这样做的原因是,在多线程环境中,传递引用的类可能会在部分构造中看到新对象,因此不一致< / em>州。这可能会导致奇怪且难以发现的错误。 IBM的这个article是众多描述它的人之一。

在这里发生的事情并不明显:匿名类实际上是内部类,因此它们包含对包含类的引用(即this正在建造)。收件人班OtherClass可能会在施工完成之前看到this,甚至可以对其进行操作。

答案 2 :(得分:0)

我建立了一个脑力图,说明了我能想到的所有不同的可能性:

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