尝试从方法返回2D对象数组时出现NullPointerException

时间:2018-04-05 12:54:50

标签: java javafx methods nullpointerexception

我正在完成一项任务,我从文本文件阅读器中制作迷宫。我已经制作了一个方法,让我选择一个文本文件并将其转换为迷宫,但我无法从该方法中提取迷宫。我在第28行获得了INullPointerException

我一直坚持为什么这个方法不能返回我的数组,以及我如何让方法返回StartX和StartY位置。

X = Maze[0].length;

编辑:

对于未来的人来说,这是我解决问题的代码:

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);
    }
}

我所做的更改如下:

  • 我使用方法内部的迷宫块创建了一个新数组,以避免出现任何范围问题。
  • 我在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); } } 循环中交换了rowi,这意味着循环现在通过一个完整的行,然后再递增到下一个循环。
  • 我将for移到text = fileScanner.nextLine();循环的内部,以便它实际扫描下一行。
  • 我改变了for循环从0开始计数而不是1(我知道这个愚蠢的错误)。

3 个答案:

答案 0 :(得分:1)

方法FileReader(名称应以小写字母开头),返回Maze
但是,这是类级别的属性,因为在try-catch中声明的具有相同名称的局部变量超出了范围。
此类级属性尚未分配,因此等于null

答案 1 :(得分:0)

这是一个范围问题。您没有返回函数“FileReader”中声明的变量,因为它仅在while循环的范围内声明。可用于返回的唯一变量是在类的范围内声明的变量。

答案 2 :(得分:0)

首先,正如其他人所指出的那样,Java命名约定是所有变量,方法和非静态字段必须以小写字母开头。当变量与现有Java SE类具有相同的名称时,这一点尤为重要。您的代码将更容易阅读,您不仅可以帮助自己,还可以更快地获得Stack Overflow上的人们的帮助。

FileReader方法中,您有以下这一行:

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

该行声明了一个名为Maze新变量,它与MazeGame类的Maze字段之间没有无关系。所有后续代码行都填充了新变量,而不是MazeGame类中声明的Maze字段。

变量仅存在于声明它的括号内的块中。在这种情况下,该块是您的try块,因为在Maze块内声明了新的try变量。到达try块的末尾后,Maze变量不存在,其值可用于垃圾回收。

当您的FileReader方法到达其return语句时,该Maze变量不存在,因此return Maze;实际上引用了MazeGame类的Maze字段。但是该字段从未由您的方法设置,因为您的代码设置了一个本地定义的变量,该变量恰好具有相同的名称。在Java中,除非另外设置,否则所有对象字段都为空。所以该方法返回null。

解决问题的最简单方法是避免定义新的Maze变量。改变这个:

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

到此:

Maze = new MazeRoute[X][Y];