[英]Local variable defined in an enclosing scope must be final or effectively final
I'm trying to print out the percentage of x/mol
, but I cannot seem to get it to work.我试图打印出
x/mol
的百分比,但我似乎无法让它工作。 I am getting a this error: Local variable x defined in an enclosing scope must be final or effectively final
我收到此错误:
Local variable x defined in an enclosing scope must be final or effectively final
It says this happens at line 22, and there is no easy fix for it.它说这发生在第 22 行,并且没有简单的解决方法。 What is java's scope, and how can I add x to the scope so that my timer can read it.
什么是 java 的范围,以及如何将 x 添加到范围以便我的计时器可以读取它。
import java.math.BigInteger;
import javax.swing.Timer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;
public class mol {
public static void main(String[] args) {
String writable = "";
BigInteger x = new BigInteger("0");
BigInteger mol = new BigInteger("602214179000000000000000");
File file = new File("molA.txt");
BufferedWriter bw = null;
FileWriter fw = null;
Timer t;
t = new Timer(10000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println(x.divide(mol) + "%");
System.out.println(x);
}
});
System.out.println("Starting...");
t.start();
do {
writable += "a";
x = x.add(new BigInteger("1"));
} while (x.compareTo(mol) < 0);
try {
fw = new FileWriter(file);
bw = new BufferedWriter(fw);
bw.write(writable);
System.out.println("Done");
} catch (IOException e) {
System.out.println(e);
} finally {
try {
if (bw != null)
bw.close();
if (fw != null)
fw.close();
} catch (IOException ex) {
System.out.println(ex);
}
}
t.stop();
System.out.println("Finished!");
}
}
You can't use a local variable inside a nested class since the JVM requires it to be final
or at least "effectively final" (which means the value of x
cannot be modified down the road).您不能在嵌套类中使用局部变量,因为 JVM 要求它是
final
或至少是“有效最终的”(这意味着x
的值不能在以后修改)。
You can by-pass it by declaring x
outside of main as a static variable:您可以通过在 main 之外将
x
声明为静态变量来绕过它:
static volatile BigInteger x = new BigInteger("0");
public static void main(String[] args) {
....
Pay attention that it is also declared to be volatile
since the main thread modified it and you want the Timer to see the updated value of x
(if you don't declare it volatile the Timer might see stale values).请注意,它也被声明为
volatile
因为主线程修改了它,并且您希望 Timer 查看x
的更新值(如果您不将其声明为 volatile,则 Timer 可能会看到陈旧的值)。
In order to use a method's local variable inside a nested class, the variable must either be either final
or "effectively final", where the latter means that the compiler can prove that that the variable's value will not change during the entire execution of the method.为了在嵌套类中使用方法的局部变量,变量必须是
final
或“有效 final”,后者意味着编译器可以证明在方法的整个执行过程中变量的值不会改变. If that condition were not satisfied then the semantics of the nested class's usage of the variable would be unclear -- which of the multiple values of the variable would be used, at which point?如果不满足该条件,则嵌套类使用变量的语义将不清楚——将使用变量的多个值中的哪一个,在哪一点?
There are several ways you could address the problem:有几种方法可以解决这个问题:
For your particular purpose, it looks like you should declare x
as a class variable instead of a local variable.对于您的特定目的,您似乎应该将
x
声明为类变量而不是局部变量。 (It cannot be an instance variable because you are accessing it from static context.) You do, however, have the alternative to (它不能是实例变量,因为您是从静态上下文访问它的。)但是,您可以选择
make x
final or effectively final.使
x
最终或有效最终。 For example, copy the reference to x
to a final
variable, and make your ActionListener
access that copy instead of accessing x
.例如,将对
x
的引用复制到final
变量,并使您的ActionListener
访问该副本而不是访问x
。
Or you could create and instantiate a named ActionListener
implementation class, nested or top-level, with a constructor to which you could pass x
.或者您可以创建并实例化一个命名的
ActionListener
实现类,嵌套的或顶级的,带有您可以传递x
的构造x
。 That implementation can then use the reference it is initialized with to access the object to which x
refers, but since BigInteger
s are immutable, it could not modify that object.然后,该实现可以使用它初始化的引用来访问
x
引用的对象,但由于BigInteger
是不可变的,因此它无法修改该对象。
Create a class to hold the BigDecimals创建一个类来保存 BigDecimals
public class MyContainer {
private BigDecimal x = null;
public MyContainer(BigDecimal x) {
this.x = x;
}
public BigDecimal getX() {
return x;
}
public void setX(BigDecimal x) {
this.x = x;
}
}
Then in your code on line 14 or so.然后在第 14 行左右的代码中。
final MyContainer myContainer = new MyContainer(new BigDecimal(0));
Then in your timer,然后在你的计时器中,
System.out.println(myContainer.getX().divide(mol) + "%");
Use the delegate pattern使用委托模式
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigInteger;
import javax.swing.Timer;
public class BigDecimalTest {
public static void main(String[] args) {
StringBuffer writable = new StringBuffer;
final MyBigInteger x = new MyBigInteger("0");
BigInteger mol = new BigInteger("602214179000000000000000");
Timer t;
t = new Timer(10000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println(x.divide(mol) + "%");
System.out.println(x);
}
});
System.out.println("Starting...");
t.start();
do {
writable.append("a");
x.add(new BigInteger("1"));
} while (x.compareTo(mol) < 0);
File file = new File("molA.txt");
try (
FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw);
) {
bw.write(writable.toString());
System.out.println("Done");
} catch (IOException e) {
System.out.println(e);
}
t.stop();
System.out.println("Finished!");
}
}
import java.math.BigInteger;
import java.util.Random;
public class MyBigInteger extends BigInteger {
private static final long serialVersionUID = 1L;
private BigInteger delegate = null;
public MyBigInteger(byte[] arg0) {
super(arg0);
delegate = new BigInteger(arg0);
}
public MyBigInteger(String arg0) {
super(arg0);
delegate = new BigInteger(arg0);
}
public MyBigInteger(int arg0, byte[] arg1) {
super(arg0, arg1);
delegate = new BigInteger(arg0, arg1);
}
public MyBigInteger(String arg0, int arg1) {
super(arg0, arg1);
delegate = new BigInteger(arg0, arg1);
}
public MyBigInteger(int arg0, Random arg1) {
super(arg0, arg1);
delegate = new BigInteger(arg0, arg1);
}
public MyBigInteger(int bitLength, int certainty, Random rnd) {
super(bitLength, certainty, rnd);
delegate = new BigInteger(bitLength, certainty, rnd);
}
@Override
public MyBigInteger divide(BigInteger divisor) {
delegate = delegate.divide(divisor);
return this;
}
@Override
public MyBigInteger add(BigInteger addition) {
delegate = delegate.add(addition);
return this;
}
@Override
public String toString() {
return delegate.toString();
}
@Override
public int compareTo(BigInteger compare) {
return delegate.compareTo(compare);
}
}
I am concerned that you are attempting to write 510Zb (510 Zetta Bytes) to a file, or even try to create a String that long.我担心您正在尝试将 510Zb(510 Zetta 字节)写入文件,甚至尝试创建一个那么长的字符串。 I would guess your system will crash because you don't have enough memory to hold the String, and you don't have enough disk space for a swap file, or to write the molA.txt file.
我猜你的系统会崩溃,因为你没有足够的内存来保存字符串,而且你没有足够的磁盘空间来存储交换文件或写入 molA.txt 文件。 If it does work, it'll probably take a long time to run.
如果它确实有效,它可能需要很长时间才能运行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.