Требуются ли в действии действующие конечные переменные JButton? [Дубликат]

На этот вопрос уже есть ответ здесь:

Невозможно обратиться к неконечной переменной внутри внутреннего класса, определенного в другом методе. 20 ответов

Так что у меня естьJList и я пытаюсь использовать его внутри сJButtonactionPerformed метод, и он просит меня сделатьJList final почему, ниже приведен фрагмент кода

public SomeClass() {    
  btnNewButton.addActionListener(new ActionListener() {
       public void actionPerformed(ActionEvent e) {
         list.clearSelection();             
    }});
}

Я неНа самом деле у меня проблемы с окончательным решением, я просто не знаю, зачем мне это нужно.

 CAMOBAP03 нояб. 2012 г., 12:37
Об этом вы можете прочитатьВот

Ответы на вопрос(3)

list переменная какfinal, они больше не являются переменными ref, но являются константами. Компилятор может просто заменить использованиеlist в анонимном классе со значениями констант (во время компиляции, конечно), и вы выигралиУ меня больше нет проблем с доступом к несуществующим переменным.

list переменная слишком ограничена, поэтому вы не можете получить к ней доступ. Если вы не сделаете этоfinal или сделайте это полем.SomeClass

УвидетьЭта статья для получения дополнительной информации

Решение Вопроса

вы должны понять основы того, как JVM использует для работы. Когда классы компилируются, которые содержат внутренние классы, генерируемый байтовый код фактически не реализует внутренние классы как класс внутри класса.

ПОЧЕМУ ОШИБКА: к локальной переменной обращались из внутреннего класса, необходимо объявить ее окончательной

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JMenu;
import javax.swing.JPanel;

public class foo extends JPanel
{  
  public foo()
  {
    final JMenu edit = new JMenu();
    edit.getItem(0).addMouseListener(new MouseAdapter(){ 
    @Override
        public void mouseClicked(MouseEvent e) 
        {
            if (e.getClickCount() == 1) {
                edit.getItem(0).setEnabled(true);
            }
        } 
    });
  }
}

Когда вы скомпилируете эту программу, будут созданы два файла: Foo.class и Foo $ 1.class. Так что теперь ваша проблема приходит, так какSecond класс то естьfoo$1.class Безразлично»не знаю, чтоVariable редактировать присутствует внутриFirst класс то естьfoo.class

Так как решить эту проблему? КакиеJVM делает, это,Требуется, чтобы разработчик объявил переменную внешнего класса как final.

Теперь, когда это сделано, JVM незаметно помещает скрытую переменную с именем val $ edit во 2-й скомпилированный файл класса, здесь вывод, полученный изjavap

Ouput для foo.class

C:\Mine\JAVA\J2SE\folder>javap foo.class
Compiled from "foo.java"
public class foo extends javax.swing.JPanel {
  public foo();
}

Теперь, поскольку редактирование является локальным для конструктора, следовательно, вывод, как указано выше.

C:\Mine\JAVA\J2SE\folder>javap foo$1.class
Compiled from "foo.java"
class foo$1 extends java.awt.event.MouseAdapter {
  final javax.swing.JMenu val$edit;
  final foo this$0;
  foo$1(foo, javax.swing.JMenu);
  public void mouseClicked(java.awt.event.MouseEvent);
}

Variable val $ edit присваивается то же значение, которое было назначено для редактирования, поскольку теперь компилятор знает, что это значение нельзя изменить, поскольку оно было объявлено как final, и, следовательно, оно работает на этот раз.

А что если я поменяюредактировать Variable из тогоLocal бытьInstance, Теперь объект класса знает все об этой переменнойредактировать, если это будет изменено. Таким образом, изменяя вышеуказанную программу, мы получаем:

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JMenu;
import javax.swing.JPanel;

public class foo extends JPanel
{  
    JMenu edit = new JMenu();

    public foo()
    {   
        edit.getItem(0).addMouseListener(new MouseAdapter(){ 
        @Override
            public void mouseClicked(MouseEvent e) 
            {
            if (e.getClickCount() == 1) {
                    edit.getItem(0).setEnabled(true);
                }
            } 
        });
    }
}

Здесь, в этом случае, мы не должны объявлять и определять его какfinalпотому что в этом случае сVariable будучи локальным для всего класса,Variable отправляется во внутренний класс вместе сObject Reference то естьthis

C:\Mine\JAVA\J2SE\folder>javap foo.class
Compiled from "foo.java"
public class foo extends javax.swing.JPanel {
  javax.swing.JMenu edit;
  public foo();
}

Вот какVariable отправляется в этом случае, т.е. это $ 0:

C:\Mine\JAVA\J2SE\folder>javap foo$1.class
Compiled from "foo.java"
class foo$1 extends java.awt.event.MouseAdapter {
  final foo this$0;
  foo$1(foo);
  public void mouseClicked(java.awt.event.MouseEvent);
}

Похоже, что интерпретация, как эта ситуация работает, по мне. Только сейчас я нашел это удивительное объяснение в интернете относительноТайна доступности в местных внутренних классах, может быть, это поможет вам лучше понять ситуацию :-)

 Paul Samsotha11 июл. 2014 г., 08:07
Я бы предложил +10 за это, если бы мог. Отличное объяснение.

Ваш ответ на вопрос