Java 如何访问AbstractButton';来自匿名内部类的方法?
这是我的班级:Java 如何访问AbstractButton';来自匿名内部类的方法?,java,swing,jpanel,jbutton,actionlistener,Java,Swing,Jpanel,Jbutton,Actionlistener,这是我的班级: public class ButtonPanel extends JPanel { public ButtonPanel () { makeButton ("button1"); makeButton ("button2"); makeButton ("button3"); } void makeButton (String name) { JButton button =new JButt
public class ButtonPanel extends JPanel {
public ButtonPanel () {
makeButton ("button1");
makeButton ("button2");
makeButton ("button3");
}
void makeButton (String name) {
JButton button =new JButton(name);
add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setText("I was clicked");
}
});
}
}
单击按钮时,其文本应更改为“我被单击”。但是,我不知道如何访问
setText
方法。我尝试了按钮.setText(“我被点击了”)
,但这是不可能的。通过将JButton
作为最终参考,如:
void makeButton(String name)
{
final JButton button =new JButton(name);
add(button);
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
button.setText("I was clicked");
}
});
}
以下是一个相关示例:
编辑1: 下面是代码的一个更新版本,其工作方式与前面提到的相同:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ButtonExample1 extends JPanel {
private JButton makeButton (String name) {
final JButton button =new JButton(name);
add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
button.setText("I was clicked");
}
});
return button;
}
private void displayGUI() {
JFrame frame = new JFrame("Button Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.add(makeButton("One"));
contentPane.add(makeButton("Two"));
contentPane.add(makeButton("Three"));
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
new ButtonExample1().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
编辑2: 下面的答案试图解释一个原因,即为什么需要将其声明为
final
要回答您的问题,您需要了解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);
}
根据我的说法,这似乎是一种解释,这种情况是如何发生的。
刚才我在网上找到了一个很好的解释,可能这会帮助你更好地了解情况:-)将JButton
作为最终参考,比如:
void makeButton(String name)
{
final JButton button =new JButton(name);
add(button);
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
button.setText("I was clicked");
}
});
}
以下是一个相关示例:
编辑1:
下面是代码的一个更新版本,其工作方式与前面提到的相同:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ButtonExample1 extends JPanel {
private JButton makeButton (String name) {
final JButton button =new JButton(name);
add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
button.setText("I was clicked");
}
});
return button;
}
private void displayGUI() {
JFrame frame = new JFrame("Button Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.add(makeButton("One"));
contentPane.add(makeButton("Two"));
contentPane.add(makeButton("Three"));
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
new ButtonExample1().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
编辑2:
下面的答案试图解释一个原因,即为什么需要将其声明为final
要回答您的问题,您需要了解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);
}
根据我的说法,这似乎是一种解释,这种情况是如何发生的。
刚才我在网上找到了一个很好的解释,可能这会帮助你更好地理解情况:-)但是我不确定如果组件被声明为final,它会如何影响组件的行为。这里有关于final类、方法和变量的信息。但是我找不到关于final组件的信息。因为您使用的是外部类的变量,在内部类中,因此出于作用域的原因,您必须将其设置为final
。我发现了一个很好的解释。一个final
组件只意味着对co的引用