编辑:
我需要改变几个变量的值,因为他们通过计时器运行几次。我需要在计时器的每次迭代中不断更新值。我不能将值设置为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);
}
对于为什么你不能做你正在尝试做的事情,已经给出了很好的解释。作为解决方案,也许可以考虑:
public class foo
{
static class priceInfo
{
public double lastPrice = 0;
public double price = 0;
public Price priceObject = new Price ();
}
public static void main ( String args[] )
{
int period = 2000;
int delay = 2000;
final priceInfo pi = new priceInfo ();
Timer timer = new Timer ();
timer.scheduleAtFixedRate ( new TimerTask ()
{
public void run ()
{
pi.price = pi.priceObject.getNextPrice ( pi.lastPrice );
System.out.println ();
pi.lastPrice = pi.price;
}
}, delay, period );
}
}
似乎你可以做一个比这更好的设计,但其思想是你可以将更新的变量分组在一个不变的类引用中。
使用匿名类时,只能从包含类中访问最终变量。因此,您需要声明正在使用的变量为final(这对您来说不是一个选项,因为您正在更改lastPrice和price),或者不要使用匿名类。
因此,您的选择是创建一个实际的内部类,您可以在其中传递变量并以正常方式使用它们
or:
对于你的lastPrice和price变量,有一个快速(在我看来很难看)的方法,就是像这样声明它
final double lastPrice[1];
final double price[1];
在匿名类中,你可以这样设置值
price[0] = priceObject.getNextPrice(lastPrice[0]);
System.out.println();
lastPrice[0] = price[0];
Java不支持真正的闭包,即使使用像您在这里使用的匿名类(new TimerTask(){…})看起来像是一种闭包。
编辑-请看下面的评论-以下是一个不正确的解释,正如keperofsoul指出的那样。
这就是为什么它不起作用:
变量lastPrice和price是main()方法中的局部变量。使用匿名类创建的对象可能会持续到main()方法返回之后。
当main()方法返回时,局部变量(如lastPrice和price)将从堆栈中清除,因此在main()返回后它们将不再存在。
但是匿名类对象引用了这些变量。如果匿名类对象在变量被清理后试图访问它们,那么事情将会发生严重的错误。
通过使lastPrice和price成为final,它们不再是真正的变量,而是常量。然后,编译器可以将匿名类中lastPrice和price的使用替换为常量的值(当然是在编译时),这样就不会再有访问不存在的变量的问题了。
其他支持闭包的编程语言是通过特殊处理这些变量来实现的——确保它们在方法结束时不会被销毁,这样闭包仍然可以访问这些变量。
你可以这样做:
public static void main(String args[]) {
int period = 2000;
int delay = 2000;
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
// Variables as member variables instead of local variables in main()
private double lastPrice = 0;
private Price priceObject = new Price();
private double price = 0;
public void run() {
price = priceObject.getNextPrice(lastPrice);
System.out.println();
lastPrice = price;
}
}, delay, period);
}