我有以下代码:
public class Outer {
public Interface Anony {
public void callback();
}
public Outer() {
OtherClass.foo(new Anony() {
@Override
public void callback() {
....
}
});
}
}
但我的朋友告诉我,它有一些问题。我在Outer的构造函数中创建了一个匿名类实例,因此匿名类实例隐式引用了外部类实例,即Outer.this。但此时,外类实例还没有完全创建。因此,匿名类实例引用具有不完整状态的对象,因此存在问题。
他是对的吗?感谢。
答案 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