Я знаю, что на это ответили серверные времена, но я не могу найти решение моей проблемы. Я пытаюсь создать очень, очень основную игру для себя, но у меня возникают проблемы с определением переменной "наличные" внутри нажатия кнопки. Мой код:
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);
}
}
});
}
Вероятно, вам нужна константа с начальной суммой наличных денег и переменной для баланса наличности (оба определены на уровне класса).
static final int INIT_CASH = 1000000;
int cash = INIT_CASH; // variable intialization
Мне кажется, что cash
не должны быть final
, и вы сделали это final
потому что компилятор сказал вам, что вы не можете сказать " cash = cash - ammount
потому что переменная cash
не была final
. Однако сделать его final
не будет, потому что вы не можете изменить значение. Так случилось?
В Java, когда метод содержит инструкцию, которая создает анонимный класс (как вы это делали с new ActionListener
), он не может ссылаться на локальные переменные метода, если они не являются final
. (Это было решение для языка. С# и 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 проще и, вероятно, более уместно.
Если вы хотите изменить стоимость наличных денег, вы не должны делать ее окончательной, поскольку она делает ее неизменной или постоянной.
Вы должны сделать переменную cash переменной экземпляра вместо метода local, потому что обычно вы хотите, чтобы он жил больше, чем один вызов метода.
public class Main{
// instance variable
int cash = 1000000;
public Main(){
// your logic
}
}