1

I'm working through a book, and the following code throws a NPE at runtime when the JButton is clicked, at the line button.actionPerformed. I've done my best to be sure my code is exactly what is in the book, can someone point out my problem? (the book was written for java 5, I'm using the latest java 7, this shouldn't make a difference in the following code as far as I know though)

import javax.swing.*;
import java.awt.event.*;

public class SimpleGui implements ActionListener {
JButton button;
public static void main(String[] args) {
    SimpleGui gui = new SimpleGui();
    gui.go();
}

public void go() {
    JFrame frame = new JFrame();
    JButton button = new JButton("click here");

    button.addActionListener(this);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    frame.getContentPane().add(button);
    frame.setSize(300,300);
    frame.setVisible(true);
}

public void actionPerformed(ActionEvent event) {
    button.setText("I've been clicked, argh!");
}

}
1
  • 1
    Well what's the stack trace? Commented Apr 27, 2013 at 18:51

5 Answers 5

3

The reason is this Line:

JButton button = new JButton("click here");

Here you are creating new local JButton object which is shadowing the member variable button . Hence button is still null. You should instead use:

button = new JButton("click here");
Sign up to request clarification or add additional context in comments.

2 Comments

So to fix it...if I change it to read <code>button = new JButton("click here");</code> then its not making a new object JButton, just a new object is being associated with JButton button, which already exists at that time? So when button.setText is called, it has somewhere to go. Is this the right way to think of it?
@nexus_2006 Yes, when you change to this code , a new JButton object will be created and this object will be referenced by the member variable of class SimpleGui . So when you call button.setText within actionPerformed, it will see that newly created object via button variable and hence no NPE
2

In a method, you have this:

JButton button = new JButton("click here");

This create the variable, but the scope of this new variable is inside the method. You've already declared button in your class though. It should just be:

button = new JButton("click here");

Comments

2

You're shadowing your variables.

You declare button as a class variable, but the re-declare within your go method, meaning that the class variable (which you reference within your actionPerformed method) is null

Change JButton button = new JButton("click here"); to button = new JButton("click here");

1 Comment

As minor modification I would say ..You declare button as instance variable (not class variable) ;)
2

Well, your JButton button; is still null.you are not assigned it anywhere in your programm

Comments

2

This problem is known as "Variable Hiding" or "Hidden Variables" or "Shadowing Variables". Which means, a local variable hides another variable which has the same name. You have re defined your variable button inside the go method. Just removed the re definition from the go method, so it will work fine. Have a look at the following code

import javax.swing.*;
import java.awt.event.*;

public class SimpleGui implements ActionListener {
JButton button;
public static void main(String[] args) {
    SimpleGui gui = new SimpleGui();
    gui.go();
}

public void go() {
    JFrame frame = new JFrame();
     button = new JButton("click here"); //Variable Re definition removed

    button.addActionListener(this);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    frame.getContentPane().add(button);
    frame.setSize(300,300);
    frame.setVisible(true);
}

public void actionPerformed(ActionEvent event) {
    button.setText("I've been clicked, argh!");
}

}

Since you seems to be new to the Java GUI, take the following few advises.

  1. It is always a best practice to define your class variables inside the constructor
  2. Use access specifiers. private is a good specifier for your button variable
  3. Even though the constructor can be automatically get created (default constructor) it is a best practice to code it by your self, at least a blank one.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.