I have a GUI class that, upon a button press, assigns a value to a private static class variable, -- let's call it strX.
The constructor of class GUI also instantiates a subclass (in the same package). This subclass implements Runnable, and starts a thread. There is an infinite loop in the thread which keeps querying the value of strX until it is no longer null. The querying is done by calling a getter method in the GUI class.
I notice that even after I have pressed the button and set strX to some non-null value, the querying in the subclass produces only null.
I am new to Java, and I am beginning to wonder if my understanding is flawed.
I've read Java: cannot access static variable from a different class in the same package and its 4 answers, which address a situation having to do with a clash of variable names. My situation is certainly not this. All I am trying to do is to use a getter method to obtain a class variable from a subclass.
Please let me know if any aspect of my question needs clarification. I would post the code, but it is long and will probably add to the confusion.
Follow-up
Okay, first of all, I'd like to thank Darren Gilroy for his detailed answer and code snippet. That cleared up some confusion in my mind, but I still had problems. So I decided to create a simple stripped-down version of my code for clarity and started testing it. This simple GUI class has two buttons, one called 'Only Instantiate', and the other called 'Set Value and Instantiate'.
When you push the 'Only Instantiate', it creates an instance of another class called PeekAtGUI. Inside PeekAtGUI, a thread is started. The thread invokes a static getter method of GUI to obtain the current value of a static class variable strX in GUI.
When you push the 'Set value and Instantiate' button, it first sets the value of strX to a new value, and then instantiates PeekAtGUI.
Please note that as I am debugging, I comment out one or other of these instantiations.
Here is the bottomline- When I try to instantiate first, and then push the other button to set the new value, PeekAtGUI doesn't seem to get the updated value. However, if I instantiate and set value with a single button push, then it all magically seems to work.
Not sure what is going on, and any clarification will be really appreciated. Thanks again.
Here is the code-
Class GUI
package intercom;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class GUI {
private JFrame frame;
private static volatile String strX = "";
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GUI window = new GUI();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public GUI() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.CENTER);
panel.setLayout(null);
JButton btnSet = new JButton("Set Value and Instantiate");
btnSet.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setVal(strX+"+");
new PeekAtGUI(); // When PeekAtGUI instantiated here, it is able to get the new strX
}
});
btnSet.setBounds(106, 94, 224, 23);
panel.add(btnSet);
JButton btnStart = new JButton("Only Instantiate");
btnStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//new PeekAtGUI(); // When PeekAtGUI is instantiated here, it is NOT able to get the new strX
}
});
btnStart.setBounds(106, 39, 224, 23);
panel.add(btnStart);
}
public static synchronized void setVal(String str){
strX = str;
GUI.class.notifyAll();
}
public static synchronized String getVal(){
return strX;
}
}
Class PeekAtGUI
package intercom;
public class PeekAtGUI implements Runnable{
private static String msg = "";
private boolean done = false;
public PeekAtGUI() {
Thread r = new Thread(this, "PeekAtGUI Thread");
r.start();
}
public void run() {
while (done == false){
try {getMsg();}catch (InterruptedException e) {e.printStackTrace();}
System.out.println("Reporting value of strX from PeekAtGUI: " + msg);
}
}
private static synchronized void getMsg() throws InterruptedException{
while((msg==GUI.getVal())){PeekAtGUI.class.wait();}
msg = GUI.getVal();
}
}