简体   繁体   中英

Reference variable to an object instantiated/initialized in another class in Java

The reason I'm asking is because I'm getting NullPointerException. I now this is very easy but I'm pretty new programming and find this a bit confusing. So say I have initialized an object in a class and want to access that same object from another class.

Like now for instance I'm working on a small Chess game, in my model Game class I have an instance of Board, an object. Board, in turn, has an array of Squares. Square[][].

Game has board, board has Square[][].

Now if I want to access the Square[][] through the object board (in Game) of type Board. Do I just declare a variable with the same name and type or do I have to initialize it again?

Board board OR Board board = new Board();

Note, I have already initialized board in the class Game so if I do it again, won't they be two totally different Board objects?

The class that refers to "board":

public class View extends JFrame {

Board      board;
JFrame     gameWindow   = new JFrame("Chess");
JPanel     gamePanel    = new JPanel();
JPanel[][] boardPanel   = new JPanel[8][8];
JMenuBar   gameMenu     = new JMenuBar();
JButton    newGame      = new JButton("New game");
JButton    pauseGame    = new JButton("Pause");
JButton    actionLog    = new JButton("Action log");

View(){
    gameWindow.setDefaultCloseOperation(EXIT_ON_CLOSE);
    gameWindow.setSize(400, 400);
    gameWindow.getContentPane().add(gamePanel);
    gameWindow.setVisible(true);
    gamePanel.setVisible(true);
    gameMenu.add(newGame);
    gameMenu.add(pauseGame);
    gameMenu.add(actionLog);
    for(JPanel[] row : boardPanel){
        for(JPanel box : row){
            gamePanel.add(box);
        }
    }
}

public void drawBoard(){
    for(int y = 0; y < 8; y++){
        for(int x = 0; x < 8; x++){
            Box box = new Box();
            box.setColour(board.getSquare(x, y).getColour());
            box.setCol(x);
            box.setRow(y);
            box.repaint();
            boardPanel[x][y].add(box);
        }
    }
}

}

class Box extends JComponent{
JPanel[][] boardPanel;
Board board;
Color boxColour;
int col, row;
public Box(){
    repaint();
}
public void paint(Graphics drawBox){
    drawBox.setColor(boxColour);
    drawBox.drawRect(50*col, 50*row, 50, 50);
    drawBox.fillRect(50*col, 50*row, 50, 50);
}
public void setColour(Color boxColour){
    this.boxColour = boxColour;
}

public void setCol(int col){
    this.col = col;
}

public void setRow(int row){
    this.row = row;
}

}

...and the class that instantiates "board":

public class Game {

@SuppressWarnings("unused")
public static void main(String[] args) 
        throws Throwable{
    Board board = new Board();
    View view = new View();
}

}

Exception happens here:

        for(JPanel[] row : boardPanel){
        for(JPanel box : row){
            gamePanel.add(box);
        }
    }

Note, I have already initialized board in the class Game so if I do it again, won't they be two totally different Board objects?

Yes, you'll then have two totally different instances. You're getting the basic idea - you have instances of objects in your program and now you have to get them to work together.

Now if I want to access the Square[][] through the object board (in Game) of type Board. Do I just declare a variable with the same name and type or do I have to initialize it again?

You have 2 ways to give Game access to the squares (probably more than just 2 depending on how you look at it):

1 Have the Board provide access to the Squares (eg a getter method on Board that returns the Squares array) so Game can access them. Board can then save the reference (have its own instance variable to hold the reference to squares, or can ask Board each time for the reference).

2 Have the Board provide methods that do the things that Game wants to do on the the squares, ie the game asks the board to do something to the squares and the board does the action on the squares.

The reason for the NPE is that the board field in the View class is not actually initialized. When you declare a field, if you don't provide an initializer by default it is initialized to null , so the statement Board board; declares a field board that refers to null .

You could eliminate the NPE by instead declaring Board board = new Board(); , but this will create a new instance, which isn't what you want. Instead, here are two options:

  1. Add a getter and setter for the board field in the View class and call it from the main method:

     public class View extends JFrame { Board board; // ... public Board getBoard() { return board; } public void setBoard(Board b) { this.board = b; } } public class Game { @SuppressWarnings("unused") public static void main(String[] args) throws Throwable{ Board board = new Board(); View view = new View(); view.setBoard(board); } 

    }

  2. Pass the parameter in the constructor, if you need to access the object from the constructor:

     public class View extends JFrame { Board board; // ... View(Board b) { this.board = b; // ... } } public class Game { @SuppressWarnings("unused") public static void main(String[] args) throws Throwable{ Board board = new Board(); View view = new View(board); } 

A third option is to use a singleton pattern as mentioned by Gursel Koca, but I prefer to avoid it when possible because it can be a pain to undo if you later decide you actually do need more than one instance of a class.

They are 2 different objects. You should not be getting NPE if you have new'd them. May be your code snippet would help here to detect the NPE or a stack trace of the NPE would help too.

Board board1 = new Board(); //creates a new Board object 
Board board2 = new Board(); //creates another new Board object

The instance of Board that you are creating in your main() method is not the same as the instance variable board of your View class. View has the following:

public class View extends JFrame { 
  Board      board;
  ...

This variable board is never assigned a value (ie a new Board())

Then, in your Game class's main method, you declare a new Board and a new View:

Board board = new Board();
View view = new View();

This variable board is a local variable of the main method, and has no relationship to the instance variable board in your View. In your View class, you need to change your variable declaration to be:

Board board = new Board();

NPE is caused by an object not being instantiated. So resolving it requires instantiation. You do that with the new operator so new Board()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM