编辑: 我需要改变几个变量的值,因为他们通过计时器运行几次。我需要在计时器的每次迭代中不断更新值。我不能将值设置为final,因为这将阻止我更新值,但是我得到了我在下面的初始问题中描述的错误:

我之前写过如下内容:

我得到错误“不能引用在不同方法中定义的内部类中的非最终变量”。 这发生在名为price的double和名为priceObject的price上。你知道我为什么会有这个问题吗?我不明白为什么我要做最后申报。如果你能看到我在做什么,我要怎么做才能解决这个问题。

public static void main(String args[]) {

    int period = 2000;
    int delay = 2000;

    double lastPrice = 0;
    Price priceObject = new Price();
    double price = 0;

    Timer timer = new Timer();

    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            price = priceObject.getNextPrice(lastPrice);
            System.out.println();
            lastPrice = price;
        }
    }, delay, period);
}

当前回答

不能引用非最终变量,因为Java语言规范是这样规定的。8.1.3: 任何使用但未在内部类中声明的局部变量、形式方法参数或异常处理程序参数必须声明为final。整个段落。 我只能看到你的代码的一部分-根据我的调度修改局部变量是一个奇怪的想法。当你离开函数时,局部变量就不存在了。也许类的静态字段会更好?

其他回答

为了避免java闭包中由匿名委托引用的变量的奇怪副作用,必须将其标记为final,因此要在计时器任务中引用lastPrice和price,它们需要标记为final。

这显然不适合您,因为您希望更改它们,在这种情况下,您应该考虑将它们封装在一个类中。

public class Foo {
    private PriceObject priceObject;
    private double lastPrice;
    private double price;

    public Foo(PriceObject priceObject) {
        this.priceObject = priceObject;
    }

    public void tick() {
        price = priceObject.getNextPrice(lastPrice);
        lastPrice = price;
    }
}

现在只需创建一个新的Foo作为final,并从计时器调用.tick。

public static void main(String args[]){
    int period = 2000;
    int delay = 2000;

    Price priceObject = new Price();
    final Foo foo = new Foo(priceObject);

    Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            foo.tick();
        }
    }, delay, period);
}

使用ClassName.this.variableName来引用非最终变量

我注意到一个没有提到的解决方案(除非我错过了,如果我错过了,请纠正我)是使用类变量。尝试在一个方法中运行一个新线程时遇到了这个问题:new thread (){Do Something}。

从下面调用doSomething()将工作。你不一定要声明它为final,只需要改变变量的作用域,这样它就不会在内部类之前被收集。当然,除非您的流程非常庞大,改变范围可能会产生某种冲突。我不想让我的变量成为final,因为它绝不是final/constant。

public class Test
{

    protected String var1;
    protected String var2;

    public void doSomething()
    {
        new Thread()
        {
            public void run()
            {
                System.out.println("In Thread variable 1: " + var1);
                System.out.println("In Thread variable 2: " + var2);
            }
        }.start();
    }

}

如果变量要求为final,那么你可以将变量的值分配给另一个变量,并使其为final,这样你就可以使用它。

如果您想在匿名类中的方法调用中更改一个值,该“值”实际上是一个Future。所以,如果你用番石榴,你可以写

...
final SettableFuture<Integer> myvalue = SettableFuture<Integer>.create();
...
someclass.run(new Runnable(){

    public void run(){
        ...
        myvalue.set(value);
        ...
    }
 }

 return myvalue.get();