如何从匿名内部类更改外部变量?

Posted

技术标签:

【中文标题】如何从匿名内部类更改外部变量?【英文标题】:How to change outer variable from anonymous inner class? 【发布时间】:2016-02-06 00:16:33 【问题描述】:

我的外部方法中有一个局部变量,我想从匿名内部类进行更改。我该怎么做?

我尝试了使用 here 描述的单元素数组的解决方案

public class outerClass
    static public void outerMethod(Interface interface) 
        final String[] variable = new String[1];
        new Thread(new Runnable() 
            @Override
            public void run() 
                variable[0] = "Hello";
                Log.i("test", variable[0]); // Works, prints "Hello"
            
        ).start();
        Log.i("test", variable[0]); // Doesn't work, null string
    

以及使用here描述的支架的解决方案

public class outerClass
    static public void outerMethod(Interface interface) 
        final Holder<String> variable = new Holder<String>;
        new Thread(new Runnable() 
            @Override
            public void run() 
                variable.held = "Hello";
                Log.i("test", variable.held); // Works, prints "Hello"
            
        ).start();
        Log.i("test", variable.held); // Doesn't work, null string
    


class Holder<String> 
    public String held;

但由于某种原因,两者都不适用于我的情况。

这可能是相关的,但不同的是我的外部方法是静态的。我还在这里简化了我的代码,原始代码是用于 android 上 Retrofit 库中的匿名回调类。

【问题讨论】:

您是否正在创建并启动Thread 来运行您的Runnable 【参考方案1】:

您正在创建一个 Runnable 类,但它实际上从未运行过。您需要通过调用它的 start() 方法来“启动”它。

但你也必须记住,当你在outerMethod()内部启动它时,它可能不会在调用Log方法之前运行(因为它将在单独的线程中运行)以及代码的顺序不再保证被调用。

【讨论】:

这不是我的实际代码,我已经简化了它,所以我忘了开始。如果一切看起来都很好,你想让我代替实际的代码吗? 我已经编辑了我的答案,以获取有关后续代码执行的线程和顺序的更多评论。 非常感谢,这确实是问题所在!日志在线程修改变量之前运行。我在线程中添加了一个 join() 以等待它完成打印日志,现在它就像一个魅力!【参考方案2】:

检查线程的同步。使用 Object.wait() 或同步关键字。您的主线程不会等到新创建的线程初始化变量。它应该等待这个完成。

顺便说一句,你的班级不可能是内部班级。见here

【讨论】:

以上是关于如何从匿名内部类更改外部变量?的主要内容,如果未能解决你的问题,请参考以下文章

这个匿名内部类为何不使用final也可以访问外部成员?

java 匿名内部类

08_Lambda表达式与匿名内部类的联系与区别

匿名内部类不能访问外部类方法中的局部变量,除非变量被声明为final类型

内部类和匿名内部类

为什么Java匿名内部类访问的外部局部变量或参数需要被final修饰