简体   繁体   English

尝试从方法返回2D对象数组时发生NullPointerException

[英]NullPointerException when trying to return 2D array of objects from a method

I'm working on an assignment where I make a maze from a text file reader. 我正在做一个作业,我用文本文件阅读器做一个迷宫。 I have made a method which lets me select a text file and convert it to a maze but I'm having trouble extracting the maze from the method. 我已经制作了一种方法,可以选择一个文本文件并将其转换为迷宫,但无法从该方法中提取迷宫。 I'm getting a NullPointerException on line 28 which is this: X = Maze[0].length; 我在第28行上得到了一个NullPointerException ,它是: X = Maze[0].length;

I'm stuck on why the method isn't returning my array and also how I can have the method return the StartX and StartY position. 我一直坚持为什么该方法不返回数组,以及如何使该方法返回StartX和StartY位置。

package Innlevering09;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import javafx.application.Application;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;

public class MazeGame extends Application {

    MazeRoute[][] Maze;
    int X;
    int Y;
    int StartX;
    int StartY;
    Player Player;

    public void start(Stage primaryStage) {
        try {
            GridPane root = new GridPane();
            Player Player = new Player(StartX, StartY);
            Maze = FileReader();

            X = Maze[0].length;
            Y = Maze.length;

            root.add(Player.getAppearance(), Player.getXpos(), Player.getYpos());

            for(int x = 0; x<X; x++){
                for(int y = 0; y<Y; y++){
                    root.add(Maze[x][y].getAppearance(), x, y);
                }
            }

            Scene scene = new Scene(root, X*10, Y*10);
            //scene.setOnKeyPressed(new FileListener(this));
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }


    public MazeRoute[][] FileReader() {
        String Text = "";
        File File;
        int Row;

        FileChooser FileChooser = new FileChooser();
        FileChooser.setTitle("Open a textfile");
        FileChooser.getExtensionFilters().add(new ExtensionFilter("Text Files", "*.txt"));
        File = FileChooser.showOpenDialog(null);

        try (Scanner FileReader = new Scanner(File)){
            X = FileReader.nextInt();
            Y = FileReader.nextInt();
            Text = FileReader.nextLine();

            MazeRoute[][] Maze = new MazeRoute[X][Y];
            while (FileReader.hasNext()){
                Text = FileReader.nextLine();

                for (int i = 0 ; i < X ; i++){
                    for (Row = 0 ; Row < Y ; Row++) {
                        char Character = Text.charAt(i);
                        switch (Character){
                        case '#':
                            Maze[i][Row] = new Wall(i, Row);
                            break;
                        case ' ':
                            Maze[i][Row] = new NormalTile(i, Row);
                            break;
                        case '-':
                            Maze[i][Row] = new EndTile(i, Row);
                            break;
                        case '*':
                            Maze[i][Row] = new NormalTile(i, Row);
                            StartX = i;
                            StartY = Row;
                            break;
                        }Row++;
                    }
                }
            }
        }catch (FileNotFoundException Error) {
            System.out.println("Cannot open file");
            Error.printStackTrace();
        }
        return Maze;
    }


    public static void main(String[] args) {
        launch(args);
    }
}

edit: 编辑:

for the people of the future this is the code where I solved the problem: 对于将来的人们,这是我解决问题的代码:

public class MazeGame extends Application {
    MazeRoute[][] maze;
    int X;
    int Y;
    int startX;
    int startY;
    Player player = new Player();



    public void start(Stage primaryStage){
        try{
            maze = fileReader();

            player.setXpos(startX);
            player.setYpos(startY);

            GridPane root = new GridPane();
            Scene scene = new Scene(root, Color.BLACK);
            Player player = new Player();

            for(int x = 0; x<X; x++){
                for(int y = 0; y<Y; y++){
                    root.add(maze[x][y].getAppearance(), maze[x][y].getTileXpos(), maze[x][y].getTileYpos());
                }
            }

            root.add(player.getAppearance(), player.getXpos(), player.getYpos());

            primaryStage.setTitle("MazeGame");
            primaryStage.setScene(scene);
            primaryStage.show();

        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public MazeRoute[][] fileReader() throws FileNotFoundException {
        String text = "";
        File file;
        FileChooser fileChooser = new FileChooser();

        fileChooser.setTitle("Open a text file with a maze");
        fileChooser.getExtensionFilters().add(new ExtensionFilter("Text Files", "*.txt"));
        file = fileChooser.showOpenDialog(null);

        Scanner fileScanner = new Scanner(file);
        X = fileScanner.nextInt();
        Y = fileScanner.nextInt();
        text = fileScanner.nextLine();

        MazeRoute[][] methodMaze = new MazeRoute [X][Y];

        while (fileScanner.hasNext()) {
            for (int row = 0 ; row < Y ; row++){
                text = fileScanner.nextLine();
                for (int i = 0 ; i < X ; i++) {
                    char character = text.charAt(i);
                    switch (character) {
                    case '#':
                        methodMaze[i][row] = new Wall(i, row);
                        break;
                    case ' ':
                        methodMaze[i][row] = new NormalTile(i, row);
                        break;
                    case '-':
                        methodMaze[i][row] = new EndTile(i, row);
                        break;
                    case '*':
                        methodMaze[i][row] = new NormalTile(i, row);
                        startX = i;
                        startY = row;
                        break;
                    }
                }
            }
        }
        return methodMaze;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

the changes I made are the following: 我所做的更改如下:

  • I made a new array with the maze blocks inside of the method to avoid the possibility of any scoping issues. 我在方法内部使用迷宫块制作了一个新数组,以避免发生任何范围确定问题的可能性。
  • I swapped the row and i in the for loop meaning that the loop now goes through a full line before incrementing down to the next one. 我在for循环中交换了rowi ,这意味着循环现在经过一整行,然后递减到下一个。
  • I moved text = fileScanner.nextLine(); 我移动了text = fileScanner.nextLine(); to the inside of the for loop so that it would actually scan the next line. for循环的内部,以便它实际扫描下一行。
  • I changed the for loops to start counting from 0 instead of 1 (stupid mistake I know). 我将for循环更改for从0而不是1开始计数(我知道这是愚蠢的错误)。

The method FileReader (whose name should start with a lower case letter), returns Maze . FileReader方法(其名称应以小写字母开头)返回Maze
However, this is the property on class level since the local variable with the same name, declared within the try-catch, is out of scope. 但是,这是类级别的属性,因为在try-catch中声明的具有相同名称的局部变量不在范围内。
This class-level property has not been assigned yet and is therefore equal to null . 该类级别的属性尚未分配,因此等于null

It's a scope problem. 这是一个范围问题。 You are not returning the variable declared in the function "FileReader" because it's declared only in the scope of the while loop. 您不会返回在“ FileReader”函数中声明的变量,因为它仅在while循环的范围内声明。 The only variable available for the return is the one declared in the scope of the class. 可用于返回的唯一变量是在类范围内声明的变量。

First, as others have pointed out, Java naming conventions are that all variables, methods, and non-static fields must start with a lower case letter. 首先,正如其他人指出的那样,Java命名约定是所有变量,方法和非静态字段必须以小写字母开头。 This is especially important when your variables have the same names as existing Java SE classes. 当变量的名称与现有Java SE类的名称相同时,这一点尤其重要。 Your code will be much easier to read, and you will not only help yourself, you will get help from people on Stack Overflow more quickly. 您的代码将更易于阅读,不仅可以帮助自己,而且可以更快地从Stack Overflow上的人员那里获得帮助。

In your FileReader method, you have this line: FileReader方法中,具有以下行:

MazeRoute[][] Maze = new MazeRoute[X][Y];

That line declares a new variable named Maze , which has no relationship to the Maze field of your MazeGame class. 该行声明了一个名为新变量 Maze ,里面有你的MazeGame类的迷宫领域没有任何关系 All subsequent lines of code are populating that new variable, not the Maze field declared in the MazeGame class. 随后的所有代码行均填充该新变量,而不是MazeGame类中声明的Maze字段。

A variable only exists within the brace-enclosed block where it is declared. 变量仅存在于声明括号的大括号内。 In this case, that block is your try block, since new Maze variable is declared inside that try block. 在这种情况下,该块就是您的try块,因为在该try块内声明了新的Maze变量。 Once the the end of that try block is reached, the Maze variable does not exist and its value is eligible for garbage collection. 一旦到达该try块的末尾, Maze变量将不存在,并且其值可以进行垃圾回收。

When your FileReader method reaches its return statement, that Maze variable doesn't exist, so return Maze; 当您的FileReader方法到达其return语句时,该Maze变量不存在,因此return Maze; actually refers to the Maze field of the MazeGame class. 实际上是指MazeGame类的Maze字段。 But that field was never set by your method, since your code was setting a locally defined variable which happened to have the same name. 但是该字段从未由您的方法设置,因为您的代码正在设置一个本地定义的变量,而该变量恰好具有相同的名称。 In Java, all object fields are null until set otherwise. 在Java中,除非另行设置,否则所有对象字段均为null。 So the method returns null. 因此该方法返回null。

The easiest way to fix your problem is to avoid defining a new Maze variable. 解决问题的最简单方法是避免定义新的Maze变量。 Change this: 更改此:

MazeRoute[][] Maze = new MazeRoute[X][Y];

to this: 对此:

Maze = new MazeRoute[X][Y];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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