在 Java 中的另一个类中实例化/初始化的对象的引用变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4662419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 07:24:41  来源:igfitidea点击:

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

javareferenceinitializationnullpointerexception

提问by Smooth Operator

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.

我问的原因是因为我收到 NullPointerException。我现在这很容易,但我是一个很新的编程,发现这有点令人困惑。所以说我已经在一个类中初始化了一个对象,并想从另一个类访问同一个对象。

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[][].

就像现在,例如我正在开发一个小型国际象棋游戏,在我的模型游戏类中,我有一个 Board 的实例,一个对象。反过来,Board 有一个 Squares 数组。正方形[][]。

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

游戏有棋盘,棋盘有 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 类型的对象板(在游戏中)访问 Square[][]。我是只声明一个具有相同名称和类型的变量还是必须再次初始化它?

Board board OR Board board = new Board();

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?

注意,我已经在类 Game 中初始化了 board,所以如果我再做一次,它们不会是两个完全不同的 Board 对象吗?

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":

...以及实例化“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);
        }
    }

回答by Bert F

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?

注意,我已经在类 Game 中初始化了 board,所以如果我再做一次,它们不会是两个完全不同的 Board 对象吗?

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?

现在,如果我想通过 Board 类型的对象板(在游戏中)访问 Square[][]。我是只声明一个具有相同名称和类型的变量还是必须再次初始化它?

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

您有 2 种方法可以让 Game 访问这些方块(根据您的看法,可能不止 2 种):

1 Have the Board provide access to the Squares (e.g. 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).

1 让 Board 提供对 Squares 的访问(例如 Board 上返回 Squares 数组的 getter 方法),以便游戏可以访问它们。Board 然后可以保存引用(有自己的实例变量来保存对方块的引用,或者每次都可以向 Board 请求引用)。

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

2 让棋盘提供方法来做游戏想在格子上做的事情,即游戏要求棋盘对格子做某事,棋盘在格子上做动作。

回答by Kevin K

The reason for the NPE is that the boardfield 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 boardthat refers to null.

NPE 的原因是boardView 类中的字段实际上没有初始化。当你声明一个字段时,如果你不提供初始化器默认情况下它会被初始化为null,所以该语句Board board;声明了一个board引用的字段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:

您可以通过改为声明来消除 NPE Board board = new Board();,但这将创建一个新实例,这不是您想要的。相反,这里有两个选项:

  1. Add a getter and setter for the boardfield 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);
    }
    
  1. board在 View 类中为字段添加 getter 和 setter,并从 main 方法中调用它:

    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. 在构造函数中传递参数,如果需要从构造函数访问对象:

    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.

第三种选择是使用 Gursel Koca 提到的单例模式,但我更愿意尽可能避免使用它,因为如果您后来决定实际上确实需要多个类的实例,那么撤消可能会很痛苦。

回答by CoolBeans

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.

它们是 2 个不同的对象。如果你有新的,你不应该得到 NPE。可能是您的代码片段在这里有助于检测 NPE,或者 NPE 的堆栈跟踪也有帮助。

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

回答by mtruesdell

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:

您在 main() 方法中创建的 Board 实例与 View 类的实例变量 board 不同。视图具有以下内容:

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

This variable board is never assigned a value (i.e. a new Board())

这个变量板永远不会被赋值(即一个新的 Board())

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

然后,在 Game 类的 main 方法中,声明一个新的 Board 和一个新的 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是main方法的局部变量,和你View中的实例变量board没有关系。在您的 View 类中,您需要将变量声明更改为:

Board board = new Board();

回答by Navi

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

NPE 是由未实例化的对象引起的。所以解决它需要实例化。你用 new 运算符来做到这一点,所以 new Board()