简体   繁体   中英

Strange behavior of Java code with static attribute

I do not have much to ask really. Heck I don't even know what the question should say. Basically, this Java code works fine without any compilation errors.

public class Application {
    static String[][] tiles;

    public Application() {
        tiles = new String[9][9];
    }

    public static void main(String[] args) {

        Application app = new Application();
        Grid mines = new Grid();
        mines.fillTiles(tiles, 9, 9, 10);
    }
}

class Grid {
    Random rand;

    public void fillTiles(String[][] tiles, int rowSize, int colSize,
            int numMines) {
        rand = new Random();
        int rowIndex;
        int columnIndex;
        while (numMines > 0) {
            rowIndex = rand.nextInt(rowSize);
            columnIndex = rand.nextInt(colSize);
            tiles[rowIndex][columnIndex] = "M";
            numMines--;
        }
    }
}

But, when I remove the line

Application app = new Application(); 

from the main method in the first class, it is throwing a NullPointerException at

tiles[rowIndex][columnIndex] = new String("M"); 

Any reason why?

Application app = new Application();

If you don't instantiate Application , tiles will be pointing to null . Operation on null reference results in NullPointerException .

Your Array initialization logic is in constructor.

public Application() {
        tiles = new String[9][9];
    }

Constructor will be executed only on Object creation ( new Application() )

If you don't want to do Application app = new Application();

Just change static String[][] tiles=new String[9][9];

Defining static array variable doesn't mean that instantiation will happen on load. It just means that that variable is class variable.

You notice that you have instantiated your array in your constructor?

static String[][] tiles;

public Application() {
    tiles = new String[9][9];  <--- Here
}

So, if you don't instantiate your Application using new Application() , your array would not be initialized, and your reference will be pointing to null.

Also, it is not a good idea to initialize your static variables in constructor. Ideally, you should initialize your static array in a static initializer block or at the place of declaration itself: -

static {
    tiles = new String[9][9];
}

or

static String[][] tiles = new String[9][9];

If you initialize your array in your constructor, it will be re-initialized for every instance, every time you create one. As static variables are common to all the instances. So, the change you make to your static variable, will be reflected in all your instances.

Because you are initializing tiles = new String[9][9]; in your constructor. You constructor is only called when you use new to create the object instance as new Application() .

If you don't want to use the constructor, declare your static variable with initialization as:

    static String[][] tiles = new String[9][9];

That should work fine without constructor call.

I think I might know the reason why:

public class Application {
    static String[][] tiles;

    public Application() {
        tiles = new String[9][9];
    }

    public static void main(String[] args) {

        Application app = new Application();
        Grid mines = new Grid();
        mines.fillTiles(tiles, 9, 9, 10);
    }
}

In this you have a static 2d array that holds strings called tiles. However, you only initialize it in the constructor of Application. Thus when calling "mines.fillTiles(tiles", tiles is still null and

tiles[rowIndex][columnIndex] = new String("M"); 

will throw a NullPointerException.

You are initializing the array in the constructor of an instance. If you create another instance after the first, it will re-initialize the static member.

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