Best way to access variables from another class?

I need to access variables from another class and I have done it using 2 different approaches described below.

My question is which of the two is preferable and why since both work quite nicely -or is there another better way to do it?. I have also done it using internal classes but this is inconvenient when the number of code lines gets growing ever larger.

In the following test code the commented asterisks repesent different files:

import java.awt.EventQueue;
import javax.swing.JFrame;

public class Test {   
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() { 
                MainFrame f = new MainFrame("Testing",50,50);
                f.setResizable(false);                  
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });   
    }
}
//**********************************************************************
import java.awt.BorderLayout;
import javax.swing.JFrame;

public class MainFrame extends JFrame {
    public MainFrame(String title,int x,int y) {
        setTitle(title);
        this.setLocation(x, y);     
        UpperPanel pUp=new UpperPanel();
        add(pUp, BorderLayout.NORTH);
            LowerPanel pLow=new LowerPanel();
            add(pLow, BorderLayout.SOUTH);
            pack();
    }
}

Now as you can see below UpperPanel must access JButtons from LowerPanel and LowerPanel must access the menu from UpperPanel. For this reason I could pass pUp as a parameter to the LowerPanel constructor but I can’t pass pLow as parameter to UpperPanel as it hasn’t been created yet.

Therefore I have used 2 methods, one declaring instances of the relevant classes and the other using static variables. The previous 2 classes above are the same in each approach.

Below is the code of the panels in the first case:

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JPanel;

public class LowerPanel extends JPanel implements ActionListener {
    static JButton butEnableMenu;
    static JButton butEnableBut1;
    public LowerPanel() {
        setLayout(new FlowLayout(FlowLayout.LEFT));
        butEnableMenu=new JButton("Enable menu");
        butEnableMenu.setEnabled(true);
        butEnableMenu.addActionListener(this);      
        add(butEnableMenu);
        butEnableBut1=new JButton("Enable first button");
        butEnableBut1.setEnabled(false);    
        butEnableBut1.addActionListener(this);  
        add(butEnableBut1);     
    }
    public void actionPerformed(ActionEvent e) {    
        UpperPanel up = null;
        Object clicked=e.getSource();
        JMenu mnu=up.myMenuBar.getMenu(0);
        if(clicked.equals(butEnableMenu)) {
            mnu.setEnabled(true);
            butEnableMenu.setEnabled(false);
        }
        else if(clicked.equals(butEnableBut1)) {
            butEnableMenu.setEnabled(true);
            butEnableBut1.setEnabled(false);
        }
    }
}
//**********************************************************************
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;

public class UpperPanel extends JPanel {
    static JMenuBar myMenuBar;
    public UpperPanel() {
        setLayout(new FlowLayout(FlowLayout.LEFT));
        myMenuBar=new JMenuBar();
        JMenu but2=new JMenu("2nd button");
        JMenuItem enableBut2=new JMenuItem("Enable");
        but2.setEnabled(false);
        enableBut2.addActionListener(new menuActionListener());
        myMenuBar.add(but2);
        but2.add(enableBut2);
        add(myMenuBar);     
    }
}

class menuActionListener implements ActionListener {
    static String clickedMenuItem=null;
    LowerPanel lp;
    public void actionPerformed(ActionEvent e) {
        clickedMenuItem=e.getActionCommand();
        JMenuItem mnuItm=(JMenuItem)e.getSource();
        JPopupMenu pmen = (JPopupMenu)mnuItm.getParent();
        JMenu pmnu =(JMenu)pmen.getInvoker();
        if(clickedMenuItem.equals("Enable")) {
            pmnu.setEnabled(false);
            lp.butEnableBut1.setEnabled(true);
        }
    }
}

And these are the panels in the second case:

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;

public class UpperPanel extends JPanel {
    static JMenuBar myMenuBar;
    public UpperPanel() {
        setLayout(new FlowLayout(FlowLayout.LEFT));
        myMenuBar=new JMenuBar();
        JMenu but2=new JMenu("2nd button");
        JMenuItem enableBut2=new JMenuItem("Enable");
        but2.setEnabled(false);
        enableBut2.addActionListener(new menuActionListener());
        myMenuBar.add(but2);
        but2.add(enableBut2);
        add(myMenuBar); 
    }
}

class menuActionListener implements ActionListener {
    static String clickedMenuItem=null;
    public void actionPerformed(ActionEvent e) {
        clickedMenuItem=e.getActionCommand();
        JMenuItem mnuItm=(JMenuItem)e.getSource();
        JPopupMenu jpm = (JPopupMenu)mnuItm.getParent();
        JMenu pmnu =(JMenu)jpm.getInvoker();
        if(clickedMenuItem.equals("Enable")) {
            pmnu.setEnabled(false);
            LowerPanel.butEnableBut1.setEnabled(true);
        }
    }
}

//**********************************************************************
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JPanel;

public class LowerPanel extends JPanel implements ActionListener {
    static JButton butEnableMenu;
    static JButton butEnableBut1;
    public LowerPanel() {
        setLayout(new FlowLayout(FlowLayout.LEFT));
        butEnableMenu=new JButton("Enable menu");
        butEnableMenu.setEnabled(true);
        butEnableMenu.addActionListener(this);      
        add(butEnableMenu);
        butEnableBut1=new JButton("Enable first button");
        butEnableBut1.setEnabled(false);    
        butEnableBut1.addActionListener(this);  
        add(butEnableBut1);
    }
    public void actionPerformed(ActionEvent e) {        
        Object clicked=e.getSource();
        JMenu mnu=UpperPanel.myMenuBar.getMenu(0);
        if(clicked.equals(butEnableMenu)) {
            mnu.setEnabled(true);
            butEnableMenu.setEnabled(false);
        }
        else if(clicked.equals(butEnableBut1)) {
            butEnableMenu.setEnabled(true);
            butEnableBut1.setEnabled(false);
        }
    }
}

Answer

In general there are 2 ways to access a variable from another class:

  1. You create an object of that class. Then this object has all the variables from the scope of that class assigned to it. For example:
Test t = new Test();
t.name = "test";
  1. You can also create a static variable. Then the variable is assigned to the class not the object of that class. This way you will not need to create an object, but all instances of the class will share the same variable.
//In the scope of the class
static String name; 

-------------------------
//when classing the class
Test.name = "The Name of the Test";

If you do not want to create a new instance of a class every time, and always use the same instance, you can create a singleton object. You write a getter method that gets you the object. It looks like this:

public class Test {
    Test t;

    public static void main(String[] args) {
       t = new Test();
    }
    
    public Test getTest() {
        if (t != null) {
            return t;
        } else {
            t = new Test();
            return t;
        }
    }
}

I see you work with a JFrame. Then you will probably want to make it a singleton. Else you will open a new instance of the JFrame every time you call upon it, which is not recommended. Does this answer your question?