本地内部类安全访问包含方法的局部变量

时间:2010-08-23 07:28:24

标签: java

定义本地内部类时,访问仅包含该方法引用的包含方法的局部变量是否安全。像这样:

public Bar containingMethod()
{
    Foo foo = new Foo();
    Bar bar = new Bar()
    {
        public void baz()
        {
            System.out.println("Accessing foo: " + foo.getValue());
        }
    };
    return bar;
};

在上面的例子中,我不确定被定义的类是否引用了foo。问题是这样做是否安全和可行,或者我在foo被调用之前是否存在bar.baz()被垃圾收集的风险?

4 个答案:

答案 0 :(得分:4)

这是安全的,但是foo需要是final的(否则你应该得到编译错误)。

Foo不会被垃圾收集,因为在引擎盖下,bar会包含对它的引用。

foo需要最终的原因是为了避免这个隐藏的引用失去同步。

从垃圾收集的角度来看,即使没有foo是最终的,它也是安全的。但是当你创建bar并且永远不会更新时,会指定对bar保持的foo的引用,因此如果允许包含方法稍后将其他内容分配给foo,则bar仍会看到“旧”对象。

请注意,final的要求仅适用于局部变量和参数,而不适用于包含类的实例字段。

答案 1 :(得分:0)

它可以是安全的,但它取决于内部类正在做什么。

您需要考虑内部类将如何使用变量。例如,如果要创建可运行或异步任务,则内部类可以从另一个线程访问该变量,甚至可以在外部方法退出后访问该变量。因此,您可能需要在使用对象之前同步该对象(例如),以防止意外问题。

此外,变量必须是最终的。这是一种语言限制,用于防止内部类在运行时更改变量的引用。这有点痛苦,如果它是语言的隐含而非明确的特征会很好。

答案 2 :(得分:0)

如果你做的是正常的事情(不是通过反思或任何东西来攻击类加载器),那就非常安全了。正如其他人所提到的,从内部对象到外部对象都有一个隐式引用(只要内部类没有定义为静态),所以它不会被垃圾收集。

根据经验,根本不可能拥有通过普通引用收集垃圾的对象的句柄。这是你不必担心的东西(它不是c ++;))

唯一的方法是通过弱引用(专门针对作业)或者通过弄乱字节码。但不是“普通”代码。

答案 3 :(得分:0)

您的代码无法编译,因此您的问题毫无意义。当您输入所需的“最终”修饰符时,代码会编译并且是安全的,这就是“最终”修饰符传达的内容。