0

本当に質問することはあまりありません。一体、私はその質問が何を言うべきかさえ知りません。基本的に、この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"); 

理由は何ですか?

4

5 に答える 5

10
Application app = new Application();

インスタンス化しない場合はApplicationtilesを指しnullます。null参照に対する操作は、結果になりNullPointerExceptionます。

配列初期化ロジックはコンストラクターにあります。

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

コンストラクターは、オブジェクトの作成時にのみ実行されます(new Application()

やりたくないならApplication app = new Application();

変更するだけ static String[][] tiles=new String[9][9];

配列変数を定義staticすることは、ロード時にインスタンス化が行われることを意味するものではありません。これは、その変数がクラス変数であることを意味します。

于 2012-11-07T18:19:57.920 に答える
5

コンストラクターで配列をインスタンス化したことに気づきましたか?

static String[][] tiles;

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

Applicationしたがって、 usingをインスタンス化しない場合new Application()、配列は初期化されず、参照はnullを指します。

また、コンストラクターで静的変数を初期化することはお勧めできません。理想的には、静的配列static initializer blockを宣言自体または宣言自体の場所で初期化する必要があります。

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

また

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

コンストラクターで配列を初期化すると、インスタンスを作成するたびに、インスタンスごとに再初期化されます。static変数はすべてのインスタンスに共通であるため。したがって、変数に加えた変更はstatic、すべてのインスタンスに反映されます。

于 2012-11-07T18:21:21.313 に答える
2

コンストラクターで初期化tiles = new String[9][9];しているためです。newコンストラクタは、オブジェクトインスタンスをとして作成するために使用する場合にのみ呼び出されますnew Application()

コンストラクターを使用したくない場合は、初期化を使用して静的変数を次のように宣言します。

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

これは、コンストラクターを呼び出さなくても正常に機能するはずです。

于 2012-11-07T18:21:22.837 に答える
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配列があります。ただし、初期化するのはApplicationのコンストラクターのみです。したがって、「mines.fillTiles(tiles」を呼び出すとき、タイルはまだnullであり、

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

NullPointerExceptionをスローします。

于 2012-11-07T18:22:09.430 に答える
0

インスタンスのコンストラクターで配列を初期化しています。最初のインスタンスの後に別のインスタンスを作成すると、静的メンバーが再初期化されます。

于 2012-11-07T18:21:07.963 に答える