简体   繁体   English

Java程序编译正常,但在运行时返回nullPointerException吗?

[英]Java program compiles fine, yet returning nullPointerException on run?

I've posted my program for review on code review (stackexchange). 我已经将我的程序发布到代码审查(stackexchange)上进行审查。 Everything worked fine, After I came home I was told to use a IDE. 一切正常,回到家后,我被告知要使用IDE。

I opened my source with Eclipse IDE, and then I started getting (both on the IDE, or without) this error upon run: 我使用Eclipse IDE打开了源代码,然后在运行时开始(无论是在IDE上还是没有)都收到此错误:

Exception in thread "main" java.lang.NullPointerException
        at games.Spin.rand(Spin.java:68)
        at games.Spin.<init>(Spin.java:10)
        at games.GameHandler.<init>(GameHandler.java:8)
        at Mains.startGame(Mains.java:16)
        at Mains.main(Mains.java:9)

Why is it doing that? 为什么这样做呢? My mate has reviewed my code, and could not find anything wrong with it?. 我的队友已经检查了我的代码,找不到任何错误吗?。

I am very new to java, tried at attempting going deeper in OO. 我对Java非常陌生,尝试过更深入的OO。

My code is located at code review thread (3 classes): 我的代码位于代码审查线程(3个类)中:

https://codereview.stackexchange.com/questions/28197/improving-my-java-object-oriented-review https://codereview.stackexchange.com/questions/28197/improving-my-java-object-iented-review

What is wrong with it? 怎么了 Why is it giving me that exception? 为什么给我那个例外?

Line 68: return r.nextInt(x); 第68行: return r.nextInt(x);

    public int rand(int x) {
        return r.nextInt(x);
    }

That's how I create r object: 这就是我创建r对象的方式:

    /**
    * Creating new Random object.
    **/

    private Random r = new Random();

Mains.java: Mains.java:

import games.GameHandler; 导入游戏.GameHandler; import java.util.Scanner; 导入java.util.Scanner; import java.io.*; 导入java.io. *;

public class Mains {

    public static void main (String[] args) {
        //Start the game
        startGame();

    }

    private static void startGame() {

        //Declares
        GameHandler handler = new GameHandler();
        Scanner console = new Scanner(System.in);   
        boolean game = true;
        String input = "";  

        //Print program welcome text
        handler.printStart();

        //While in game...
        while (game) {
            //Getting input ready for new commands from the player
            input = console.nextLine();

            //Checking if input was set.
            if (input != null) {
                //Selecting the game you want to play.
                handler.selectGame(input);

                //If game was selected.. then.. let's start playing.
                while (handler.inGame) {
                    //Use will say something.
                    input = console.nextLine();

                    //If it was "exit", it will go back and select another game.
                    if (input.equals("exit")) {
                        handler.exitGame();
                    } else {
                        //Play again.
                        handler.continueGame(input);
                    }
                }
            }
        }
    }
}

GameHandler.java: GameHandler.java:

package games; 包装游戏; import java.io.*; 导入java.io. *;

public class GameHandler {

    private String[] games = {"Spin", "Tof"};
    private String[] navigation = {"Back", "Start"};
    private Spin spin = new Spin();
    private boolean spinGame = false;
    private boolean tofGame = false;
    public boolean inGame = false;

    /**
    * Method printStart
    *
    * Will welcome the player to the program.
    */
    public void printStart() {

        this.print(0, "Welcome to the program!");
        this.print(0, "Please select a game: " + this.availableGames());

    }

    /**
    * Method available games
    *
    * This will print all the games that are located in the games array in one row.
    **/

    private String availableGames() {
        String names = "";
        for (int i = 0; i < games.length; i++) {
            names = (names + games[i]);
            if (i < games.length -1) {
                names = (names + ", ");
            }
        }

        return names;
    }

    /**
    * Method selectGame
    *
    * This will select the given game.
    * @param command The entered command.
    **/

    public void selectGame(String command) {
        if (this.inArray(command))
        {
            if (command.equalsIgnoreCase("spin")) {
                this.startGame("spin");
            } else if (command.equalsIgnoreCase("tof")) {
                this.startGame("tof");
            }
        } else {
            this.print(0, "Could not find game!");
        }
    }

    /**
    * Method inArray
    *
    * This will check if the entered game name is exisiting in the games array.
    * If yes, will return a boolean true, else false.
    *
    * @param value The entered game name.
    * @return boolean true/false.
    **/

    private boolean inArray(String value) {
        int returning = 0;
        for (String s : games) {
            if (value.equalsIgnoreCase(s)) {
                returning = 1;
            }
        }
        if (returning == 1) {
            return true;
        } else {
            return false;
        }
    }

    /**
    * Method startGame
    *
    * Will start the game, and print instructions.
    * will set the game boolean to true.
    **/

    private void startGame(String game) {
        switch (game) {
            case "spin":
                this.print(0, "Welcome to spin game!");
                this.print(0, "Please click on any key to spin!");
                spinGame = true;
            break;
            case "tof":
            break;
        }

        inGame = true;
    }

    /**
    * Method continueGame
    *
    * Will continue the game, either spin again, or print new question or even answer.
    * @param command The entered command.
    **/
    public void continueGame(String command) {
        while (inGame) {
            if (spinGame) {
                this.spinWheel();
                // Break out of the loop.
                break;
            }
        }
    }

    /**
    * Method exitGame
    *
    * Exit the game..
    **/

    public void exitGame() {
        spinGame = false;
        tofGame = false;
        this.printStart();
    }

    /**
    * Method spinWheel
    *
    * This will spin the wheel.
    **/

    private void spinWheel() {
        this.print(0, spin.spinWheel());
    }

    /**
    * Method print
    *
    * Prints text using System.out
    * @param type printing type (Println/print).
    * @param message The message
    **/

    private void print(int type, String message) {
        switch (type) {
            case 0:
                System.out.println(message);
            break;
            case 1:
                System.out.print(message);
            break;              
        }
    }
}

Spin.java: Spin.java:

package games; 包装游戏; import java.util.Random; 导入java.util.Random;

public class Spin {

    /**
    * The base auth we are going to work with..
    **/

    private int auth = this.rand(1000) / 5; 

    /**
    * Creating new Random object.
    **/

    private Random r = new Random();

    /**
    * Method spinWheel
    *
    * Spins the damn wheel..
    * @return spinned value + if you won or not.
    **/

    public String spinWheel() {
        return this.spinWheel(this.rand(100));
    }

    /**
    * spinWheel
    *
    * Returning results.
    **/

    private String spinWheel(int number) {

        int result = this.Calculate(this.rand(number));

        if (result < 101) {
            return "You have won the game!" + result;
        } else {
            return "You've lost the game!" + result;
        }
    }

    /**
    * Method calculate
    *
    * Calculates the spin.
    * @return the spinned number.
    **/


    private int Calculate(int Number) {

        int var = this.rand(101);

        int holder = (var * Number) / 2;

        return holder + this.auth;
    }

    /**
    * Shortcut for nextInt of Random
    **/

    public int rand(int x) {
        return r.nextInt(x);
    }

}

rand is invoked before the Random instance r is initialised. 在初始化Random实例r之前调用rand Switch the order or these 2 statements 切换顺序或这2条语句

private int auth = this.rand(1000) / 5; 
private Random r = new Random();

should be 应该

private Random r = new Random();
private int auth = this.rand(1000) / 5; 

Make the assignment of r the first thing in your Spinwheel class definition, ie put it before it is used in this.rand(1000): 使r的赋值成为您的Spinwheel类定义中的第一件事,即,将其放在this.rand(1000)中使用之前:

public class Spin {
  /**
   * Creating new Random object.
   **/
  private Random r = new Random();

  /**
   * The base auth we are going to work with..
   **/
  private int auth = this.rand(1000) / 5; 

r is null, so you can't call any instance method on r . r为null,因此您不能在r上调用任何实例方法。 Make sure you intialize r before using it. 使用前请确保将r初始化。

More specifically, in this line: 更具体地说,在这一行:

private int auth = this.rand(1000) / 5; 

you're calling the rand() method before r has been initialized (it's initialized right after). 您正在r初始化之前(在之后立即初始化rand()调用rand()方法。

This is the line causing the NullPointerException : 这是导致NullPointerException的行:

private int auth = this.rand(1000) / 5; 

Since this line comes before the initialization for r , you are invoking rand before r was initialized. 由于此行位于r的初始化之前 ,因此您要 r初始化之前调用rand In that case r is null in rand and that's your exception. 在这种情况下, rrandnull ,这是您的例外。

This is obvious from your stack trace: 从堆栈跟踪中可以明显看出:

at games.Spin.rand(Spin.java:68)
at games.Spin.<init>(Spin.java:10)

Note that the exception is happening in the initializer . 请注意, 初始化程序中发生了异常。 From there, it's easy to back out what is going on. 从那里,很容易退回正在发生的事情。

You need to initialize r first, that is, move the initialization line for r before the initialization line for auth . 您需要初始化r第一个,也就是移动起始线为r的起始线之前auth Thus: 从而:

private Random r = new Random();
private int auth = this.rand(1000) / 5; 

This is because r is being used before it is instantiated within statement private int auth = this.rand(1000) / 5; 这是因为在语句private int auth = this.rand(1000) / 5; r实例化之前已在使用它private int auth = this.rand(1000) / 5; . So , JVM is seeing r as null , which is leading to NPE . 因此,JVM将r视为null ,这导致了NPE To get rid of this problem within Spin class declare the fields as follows: 要摆脱Spin类中的此问题,请声明字段,如下所示:

    private Random r = new Random();
    private int auth = this.rand(1000) / 5; 

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

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