Я использую actionListener с событием JComboBox. Я хочу отключить прослушиватель, когда вручную устанавливаю элемент, выбранный в моей программе.
Здесь вы можете увидеть это-
String item=null;
String isSetByProgram=false;
jcb1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae){
if (isSetByProgram)
return;
item=jcb1.setSelectedItem();
}
});
//Now set by program
isSetByProgram = true;
jcb1.setSelectedItem("customItem1");
isSetByProgram=false;
Но вот что я получаю:
ошибка: локальные переменные, на которые ссылается внутренний класс, должны быть окончательными или фактически окончательными
Как я могу сделать это, не создавая еще один отдельный класс, расширяющий JComboBox?




Насколько я знаю, вы не можете. Это связано с тем, что ваш анонимный класс работает с копией переменной, которая (если не окончательная) может быть изменена, и в этом случае это запрещено.
Да, именно так работает final, вы не можете изменить конечное значение переменной или конечную ссылку, если это ссылка на объект.
Вы знаете какой-либо другой подход?
Вы можете попробовать написать класс, у которого будет параметр isSetByProgram. Создайте из него объект и отправьте анонимному классу окончательную ссылку на этот объект. Этот объект не будет изменен, но его значение может быть изменено. Должно сработать (не тестировал).
Переместите item и isSetByProgram в закрытые поля вашего класса. Поля экземпляра существуют специально для хранения состояния.
public class MyApplication {
private boolean isSetByProgram;
private String item;
// ...
jcb1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae){
if (isSetByProgram) {
return;
}
item = jcb1.getSelectedItem();
}
});
//Now set by program
isSetByProgram = true;
jcb1.setSelectedItem("customItem1");
EventQueue.invokeLater(() -> { isSetByProgram = false; });
почему EventQueue.invokeLater (() -> {isSetByProgram = false;}); написано??
Поскольку при вызове jcb1.setSelectedItem события помещаются в очередь событий AWT. Если вы выполните isSetByProgram = false; немедленно, это может быть false до запуска ActionListener. Таким образом, вы можете быть уверены, что устанавливаете для него значение false после обработки ActionEvent.
Я пробовал с final, но в конечном итоге вы не можете изменить значение при использовании final