为什么在将对象作为参数传递给JButton类的addActionListener()方法时使用此关键字?

时间:2016-11-22 11:39:54

标签: java swing nullpointerexception jframe jbutton

所以我开始使用Java中的javax.swing包类。我创建了一个按钮,并希望为它添加功能,所以我实现了ActionListener接口来监听我的按钮创建的事件

这是代码块。

public class SimpleGUI  implements ActionListener {     
    JButton button;

public void go() {
    JFrame frame = new JFrame();
    button = new JButton("Click me");

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(button);
    frame.setSize(300, 300);
    frame.setVisible(true);

    button.addActionListener(this);
}

@Override
public void actionPerformed(ActionEvent event) {
    button.setText("I've been clicked");
}

当我在API中查找addActionListener方法时,它声明传递的参数应该实现ActionListener接口但是当我调整方法的最后一行go()代码为

    button.addActionListener(new SimpleGUI());

我相信这应该运行得很好而且编译器看起来也不错但是当我运行它时,毕竟我传递了实现ActionListener接口的对象,但是我得到了大量的运行时错误。

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at simplegui.SimpleGUI.actionPerformed(SimpleGUI.java:29)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6533)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6298)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

有人可以解释这背后的原因吗?

2 个答案:

答案 0 :(得分:3)

当您将this传递给.addActionListener()方法时,您将传递对您班级的当前实例的引用。传入new SimpleGUI()时,传入新创建的实例。新创建的实例没有评估您的button对象的实例,从而生成您在尝试设置文本时看到的错误。

此外,由于评论中提到了Hovercraft Full Of Eels,因此在另一个类上实现ActionListener接口,然后将其传递给.addActionListener()会更好。

您还可以使用Anonymous Class,如下所示:

button.addActionListener(new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {

            button.setText("I've been clicked");
        }
    });

这样做会在现场定义您的ActionListener,并且一旦您开始进入更大的应用程序,就可以生成更清晰的代码。

答案 1 :(得分:1)

侦听器的按钮变量为null,因为侦听器的SimpleGUI对象与显示的对象不同(如上所述),从不调用侦听器对象的go()方法,因此永远不会为按钮分配有效对象。

但是假设您已经摆脱了go()方法并在SimpleGUI构造函数中进行了所有初始化,而您的代码将不会抛出NullPointerException,它将无法正常运行,因为您已经更改侦听器的SimpleGUI对象显示的文本(更改状态),而不是显示的 SimpleGUI对象。

正如Gulllie所说,使用内部匿名类,私有内部类或完全独立的侦听器类。