无法分配最终的局部变量,因为它是在封闭类型中定义的

时间:2014-12-28 05:33:20

标签: java variables int

我知道这已经回答了很多次,但我似乎无法找到解决问题的方法。我正在尝试为自己创建一个非常非常基本的游戏,但是我在按钮点击内部定义变量“cash”时遇到了问题。我的代码是:

public Main() {
    final int cash = 1000000;
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);

    JLabel lblCash = new JLabel("Cash: " + cash);
    lblCash.setBounds(10, 11, 166, 14);
    contentPane.add(lblCash);

    JButton btnStake = new JButton("STAKE");
    btnStake.setBounds(258, 227, 166, 23);
    contentPane.add(btnStake);

    final JLabel lblwol = new JLabel("");
    lblwol.setBounds(10, 115, 414, 14);
    contentPane.add(lblwol);

    sa = new JTextField();
    sa.setBounds(10, 228, 238, 20);
    contentPane.add(sa);
    sa.setColumns(10);

    btnStake.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent arg0) {
            String stringAmmount = sa.getText().toString();
            int ammount = Integer.parseInt(stringAmmount);
            sa.setText("");

            double comp = Math.random();

            if (comp < 0.5){
                lblwol.setText("Congratulations, you have won: " + ammount);
                cash = cash - ammount;
            } else {
                lblwol.setText("Sorry, you have lost: " + ammount);
            }
        }

    });
}

3 个答案:

答案 0 :(得分:2)

您可能需要一个常数,包括初始现金金额和现金余额变量(均在班级定义)。

static final int INIT_CASH = 1000000;

int cash = INIT_CASH; // variable intialization

答案 1 :(得分:0)

如果您希望现金的值发生变化,则不应将其设为最终,因为它会使其保持不变或不变。

您应该将现金变量设为实例变量而不是本地方法,因为通常您希望它比一个方法调用更多。

public class Main{
  // instance variable
  int cash = 1000000;

  public Main(){
  // your logic
  }

}

答案 2 :(得分:0)

在我看来,cash不应该是final,而你是final,因为编译器告诉你,你不能说cash = cash - ammount,因为变量cash不是final。但是,使其final无法正常工作,因为您无法修改该值。那是怎么回事?

在Java中,当一个方法包含一个创建匿名类的语句时(正如你对new ActionListener所做的那样),它不能引用方法的局部变量,除非它们是final。 (这是一个语言设计决定.C#和JavaScript,有类似的结构,没有这个限制。)这里你有一个构造函数,它不是一个真正的方法,但它的行为就像一个方法。有两种方法:

1)使变量成为实例字段,而不是局部变量。因此,您在构造函数之外说int cash = 1000000

当每个对象只能有一个这样的变量时,这是一个合适的解决方案。它也适用于您的情况,因为您在构造函数中有cash。每个对象不能多次调用构造函数,因此对象只能有一个cash

但是,有些情况下,这不会起作用,其中变量是在方法中而不是构造函数中声明的。假设您有一个创建新按钮的方法,并且可能会通过多次调用此方法创建多个按钮,并且每个新按钮都有自己的侦听器,每个按钮都有自己的修改变量。现在只有一个对象的实例变量不起作用。因此解决final问题的另一种方法是:

2)使变量成为其他对象内的一个字段。你可以声明一个只包含cash字段的非常简单的类:

private static class Wallet {   // a Wallet holds cash, hee hee hee
    public int cash;
    public Wallet(int cash) { this.cash = cash; }
}

并在您的方法中

final Wallet wallet = new Wallet(1000000);

现在,匿名类可以引用wallet,因为它是final。但只有Wallet对象的引用是最终的,而不是字段;所以匿名类仍然可以修改wallet.cash。 (另一种创建对象的方法是使它成为一个元素的数组。在我看来,声明一个新类更具可读性。)

我提到这一点,以便您知道如何在问题出现时解决问题 - 并且它确实经常出现。但是,在您的情况下,解决方案1更简单,可能更合适。