简体   繁体   English

在封闭作用域中定义的局部变量必须是最终的或有效的最终变量

[英]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:有几种方法可以解决这个问题:

  1. 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 (它不能是实例变量,因为您是从静态上下文访问它的。)但是,您可以选择

  2. 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

  3. 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.

相关问题 在封闭 scope 中定义的局部变量迭代必须是最终的或有效的最终 - local variable iteration defined in an enclosing scope must be final or effectively final 在封闭 scope 中定义的局部变量 ObjList 必须是最终的或有效的最终 - Local variable ObjList defined in an enclosing scope must be final or effectively final 在封闭范围内定义的局部变量 log 必须是 final 或有效 final - Local variable log defined in an enclosing scope must be final or effectively final 线程:封闭范围中定义的局部变量必须是final或有效的final - Threads: Local variable defined in an enclosing scope must be final or effectively final 我在封闭作用域中定义的局部变量必须是最终的或有效的最终变量 - Local variable i defined in an enclosing scope must be final or effectively final 在封闭的 scope 中定义的局部变量 collect 必须是最终的或有效的最终的 - Local variable collect defined in an enclosing scope must be final or effectively final 封闭范围中定义的局部变量textfeild_1必须是final还是有效的final? - local variable textfeild_1 defined in an enclosing scope must be final or effectively final? 计时器错误的int值:在封闭范围内定义的局部变量ans必须是final或有效的final - int for timer error: Local variable ans defined in an enclosing scope must be final or effectively final 在封闭范围内定义的局部变量 statusMessage 在返回新对象时必须是最终的或有效的最终 - Local variable statusMessage defined in an enclosing scope must be final or effectively final on returning a new object Java 8 显示此错误。 在封闭作用域中定义的局部变量 itemList 必须是 final 或有效 final - Java 8 shows this error. Local variable itemList defined in an enclosing scope must be final or effectively final
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM