2012-11-07 2 views
0

У меня не так много, чтобы спросить действительно. Черт, я даже не знаю, что должен сказать этот вопрос. В принципе, этот Java-код отлично работает без ошибок компиляции.Странное поведение 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--; 
     } 
    } 
} 

Но, когда я удалить строку

Application app = new Application(); 

от основного метода в первом классе, он бросает NullPointerException на

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

Любая причина, почему?

+0

, потому что плитка является пустой. – proflux

ответ

5

Вы заметили, что вы создали экземпляр своего массива в своем конструкторе?

static String[][] tiles; 

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

Так что, если вы не создаете экземпляр вашей Application с помощью new Application(), ваш массив не будет инициализирован, и ваша ссылка будет указывать на нуль.

Кроме того, не стоит инициализировать свои статические переменные в конструкторе. В идеале, вы должны инициализировать статический массив в static initializer block или на месте самой декларации: -

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

или

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

Если инициализировать массив в конструкторе, он будет повторно инициализирован для каждого экземпляра, каждый раз, когда вы его создаете. Поскольку переменные static являются общими для всех экземпляров. Таким образом, внесение изменений в вашу переменную static будет отражено во всех ваших экземплярах.

+0

Черт! О чем я думал! спасибо. – r3st0r3

10
Application app = new Application(); 

Если вы не создаете экземпляр Application, tiles будет указывать null. Операция с нулевыми ссылочными результатами в NullPointerException.

Логика инициализации вашего массива находится в конструкторе.

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

Конструктор будет выполняться только при создании объекта (new Application())

Если вы не хотите делать Application app = new Application();

Просто измените static String[][] tiles=new String[9][9];

Определение переменных static массива не означает, что инстанцирование произойдет при загрузке. Это просто означает, что эта переменная является переменной класса.

0

Вы инициализируете массив в конструкторе экземпляра. Если вы создадите другой экземпляр после первого, он будет повторно инициализировать статический член.

+0

Нет, он * инициализацию * массив в конструкторе. Это * объявлен * в области видимости класса (как и следовало бы, учитывая, что это статическая переменная). –

+0

oops - исправлено, что –

2

Потому что вы инициализируете tiles = new String[9][9]; в своем конструкторе. Конструктор вызывается только при использовании new для создания экземпляра объекта как new Application().

Если вы не хотите использовать конструктор, объявить статическую переменную с инициализацией, как:

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

Это должно работать нормально без вызова конструктора.

2

Я думаю, что я мог бы знать причину, почему:

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

В этом у вас есть статический 2d массив, который содержит строки, называемые плитки. Однако вы только инициализируете его в конструкторе приложения. Таким образом, при вызове «mines.fillTiles (плитки», плитки по-прежнему утратившая

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

кинет NullPointerException.

Смежные вопросы