简体   繁体   English

具有静态属性的Java代码的奇怪行为

[英]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. 基本上,此Java代码可以正常工作,没有任何编译错误。

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 从第一类的主要方法中,它在抛出NullPointerException

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 . 如果不实例化Applicationtiles将指向null Operation on null reference results in NullPointerException . 对空引用进行操作会导致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() ) 构造函数将仅在创建对象时执行( new Application()

If you don't want to do Application app = new Application(); 如果您不想执行Application app = new Application();

Just change static String[][] tiles=new String[9][9]; 只需更改static String[][] tiles=new String[9][9];

Defining static array variable doesn't mean that instantiation will happen on load. 定义static数组变量并不意味着实例化将在加载时发生。 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. 因此,如果不使用new Application()实例化您的Application ,则不会初始化您的数组,并且您的引用将指向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 initializer block或在声明本身的位置初始化静态数组:-

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. 由于static变量是所有实例共有的。 So, the change you make to your static variable, will be reflected in all your instances. 因此,您对static变量所做的更改将反映在所有实例中。

Because you are initializing tiles = new String[9][9]; 因为您正在初始化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() . 仅当使用new将对象实例创建为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. 在这种情况下,您有一个静态2d数组,其中包含称为tile的字符串。 However, you only initialize it in the constructor of Application. 但是,您只能在Application的构造函数中对其进行初始化。 Thus when calling "mines.fillTiles(tiles", tiles is still null and 因此,当调用“ mines.fillTiles(tiles)”时,tile仍为null,并且

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

will throw a NullPointerException. 将抛出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. 如果在第一个实例之后创建另一个实例,它将重新初始化静态成员。

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

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