【问题标题】:Modifying an outer variable within an anonymous inner class在匿名内部类中修改外部变量
【发布时间】:2014-12-26 20:28:54
【问题描述】:

据我了解,内部匿名类中使用的任何变量(但在其外部声明)实际上都会传递其值的副本。还需要将这些外部变量声明为 final,这显然意味着这些变量不应该被修改。

但是有什么解决方法吗?我的匿名内部类实际上可以修改一些变量或对象,然后我可以稍后在我的代码中(在匿名类之外)使用它们吗?还是在匿名类之外看不到修改?

【问题讨论】:

  • 不,只有局部变量(或参数)有这个限制。

标签: java anonymous-function anonymous-class


【解决方案1】:

您所指的行为仅适用于局部变量或方法/捕获参数。您可以很好地访问并可能修改实例成员

public class Example {

    public void method() {
        String localFoo = "local";
        new Object() {
            public void bar() {
                foo = "bar"; // yup
                System.out.println(localFoo); // sure
                localFoo = "bar"; // nope
            }
        };        
    }

    private String foo = "foo";
}

匿名Object 内部类复制localFoo 的值以在println(..) 调用中使用。然而,对于foo,它实际上是在“复制”对Example 实例的引用并引用它的foo 字段。

其实相当于

Example.this.foo = "bar";

【讨论】:

  • 感谢您的回复。如果您实例化此 Example 对象,对其调用 method(),然后尝试打印 'foo' 字段,它似乎仍然保留为 'foo' 而不是 'bar'。这是为什么呢?
  • @Decoy 你没有调用bar()
  • 愚蠢的错误!谢谢。
  • 明确一点,以您的示例为例,绝对没有办法修改匿名类中的 localFoo 变量?
  • @Decoy 没错。 method 中声明的局部变量 localFoo 不能在方法主体或匿名类主体中的任何地方修改,假设它正在匿名类中使用。
【解决方案2】:

引用的对象确实需要是最终的 - 但是,它们可以是可变的。

class Holder<T> {
    public T held;
}

public void test() {
    final Holder<String> s = new Holder<>();
    new Runnable () {

        @Override
        public void run() {
            s.held = "Hello;";
        }

    }
}

这大大简化了 - 您通常会使用 getter 和 setter 来保存值。

【讨论】:

  • 优秀的解决方案!谢谢!
猜你喜欢
  • 1970-01-01
  • 2019-02-04
  • 2023-03-28
  • 1970-01-01
  • 2016-11-10
  • 2018-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多