Java 内置JButton';是否需要执行最终变量的操作?

Java 内置JButton';是否需要执行最终变量的操作?,java,swing,jbutton,jlist,final,Java,Swing,Jbutton,Jlist,Final,因此,我有一个JList,我试图在JButtonsactionPerformed方法中使用它,它要求我将JList设置为final为什么,下面是一个代码片段 public SomeClass() { btnNewButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { list.clearSelection();

因此,我有一个
JList
,我试图在
JButton
s
actionPerformed
方法中使用它,它要求我将
JList
设置为final
为什么,下面是一个代码片段

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

实际上,我在将其设置为最终类时没有遇到任何问题,我只是不确定为什么需要这样做。

您正在创建一个匿名类,并且
列表
变量的范围太有限,因此您无法访问它。除非将其设置为
最终
或将其设置为
某个类的字段


有关更多信息,请参见

您正在创建一个匿名类,
列表
变量的范围太有限,因此无法访问它。除非将其设置为
最终
或将其设置为
某个类的字段


有关更多信息,请参见,通过将
列表
变为
最终
,它们实际上不再是变量ref,而是常量。然后,编译器就可以用常量的值(当然是在编译时)替换匿名类中使用的
list
,这样您就不会再有访问不存在的变量的问题了。

通过将
list
变量设置为
final
,它们不再是真正的变量ref,但是常数。然后,编译器就可以用常量的值(当然是在编译时)替换匿名类中使用的
list
,这样您就不会再有访问不存在的变量的问题了。

要回答您的问题,您需要了解JVM如何工作的基本知识。 当编译包含内部类的类时,生成的字节码实际上并没有将内部类作为类内的类来实现

错误原因:局部变量是从内部类访问的,需要将其声明为final

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。现在问题来了,因为
第二个
类,即
foo$1.class
不知道
变量
编辑存在于
第一个
类,即
foo.class

那么如何解决这个问题呢?
JVM
所做的是,它要求开发人员将外部类的变量声明为final

现在这样做了,现在JVM在第二个编译的类文件中悄悄地放置了一个名为val$edit的隐藏变量,下面是从
javap

foo.class的输出

C:\Mine\JAVA\J2SE\folder>javap foo.class
Compiled from "foo.java"
public class foo extends javax.swing.JPanel {
  public foo();
}
现在,由于edit是构造函数本地的,因此输出如上所述

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);
}
变量
val$edit被分配了与分配给edit的值相同的值,因为现在编译器知道该值不能更改,因为它已被声明为最终值,因此这次可以工作

现在,如果我将edit
变量
本地
更改为
实例
,该怎么办。现在,如果这个变量被修改,类的对象就知道它的一切。因此,同样改变上述程序,我们得到:

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
,因为在这种情况下,由于
变量
是整个类的局部变量,因此
变量
对象引用一起发送到内部类,即
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();
}
以下是在这种情况下如何发送
变量
,即$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);
}
根据我的说法,这似乎是一种解释,这种情况是如何发生的。
刚才我在互联网上找到了一个很好的解释,可能这将帮助您更好地了解情况:-)

要回答您的问题,您需要了解JVM如何工作的基础知识。 当编译包含内部类的类时,生成的字节码实际上并没有将内部类作为类内的类来实现

错误原因:局部变量是从内部类访问的,需要将其声明为final

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。现在问题来了,因为
第二个
类,即
foo$1.class
不知道
变量
编辑存在于
第一个
类,即
foo.class

那么如何解决这个问题呢?
JVM
所做的是,它要求开发人员将外部类的变量声明为final

现在这样做了,现在JVM在第二个编译的类文件中悄悄地放置了一个名为val$edit的隐藏变量,下面是从
javap

foo.class的输出

C:\Mine\JAVA\J2SE\folder>javap foo.class
Compiled from "foo.java"
public class foo extends javax.swing.JPanel {
  public foo();
}
现在,由于edit是构造函数本地的,因此输出如上所述

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);
}
变量
val$edit被分配了与分配给edit的值相同的值,因为现在编译器知道该值不能更改,因为它已被声明为最终值,因此这次可以工作

现在,如果我将edit
变量
本地
更改为
实例
,该怎么办。现在,如果这个变量被修改,类的对象就知道它的一切。因此,同样改变上述程序,我们得到:

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
,因为在这种情况下,由于
变量
是整个类的局部变量,因此
变量
对象引用一起发送到内部类,即
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();
}
以下是在这种情况下如何发送
变量
,即$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);
}
根据我的说法,这似乎是一种解释,这种情况是如何发生的。 只是