1

次のことについて教えていただけませんか。

スニペット1:

public class ArrayKoPo {

    public static int[] getArray() {
        return null;
    }

    public static void main(String args[]) {
        int i = 0;
        try {
            int j = getArray()[i++];
        } catch (Exception e) {
            System.out.println(i); //prints 1 <---- This one I expected.
        }
    }
}

スニペット2:

public class ArrayKoPo {

    public static int[][] getArray() {
        return null;
    }

    public static void main(String args[]) {
        int i = 0;
        try {
            int j = getArray()[i++][i++];
        } catch (Exception e) {
            System.out.println(i); //still prints 1 <---- This one I don't understand. I thought 2 will be printed.
        }
    }
}

コードの2番目のブロックで変数iが2回インクリメントされないのはなぜですか?

私は何が欠けていますか?

ありがとう。

4

2 に答える 2

2

私はそれが次のように起こると信じています:

  1. プログラムはgetArray()まで実行されます。nullが返されます。
  2. 次に、プログラムは角かっこに移動し、引数を評価して、配列に入ろうとします。(私がよく知らないJavaの魔法はここで起こります)
  3. 2番目のインデックス演算子が調べられる前に、試行は失敗し、例外が生成されます。

2番目のスニペットを別の方法で配置する場合は、次のようになります(したがって、最初のスニペットと同じ結果が生成されます)。

public class ArrayKoPo {

    public static int[][] getArray() {
        return null;
    }

    public static void main(String args[]) {
        int i = 0;
        try {
            int[] j = getArray()[i++];
            int k = j[i++];
        } catch (Exception e) {
            System.out.println(i);
        }
    }
}
于 2012-08-22T05:09:04.243 に答える
1

私のコメントで述べたように...

まず、Javaは左から右に評価することに注意することが重要です。配列として扱われるgetArray()[i++]の要素にアクセスしようとすると、が生成されることがわかります。この例外は、外部配列アクセス式が評価される前に式の評価を中断します(そのインデックスはとして計算されます)。したがって、2番目のインクリメントは発生しません:-)nullNullPointerExceptiongetArray()[i++][i++]i++


これは、配列アクセス式について説明しているJava言語仕様の§15.13に準拠しています。

ArrayAccess:
    ExpressionName [ Expression ]
    PrimaryNoNewArray [ Expression ]

式の評価の段階的な手順は、§15.13.1配列アクセスの実行時評価に明確に記載されています。

配列アクセス式は、次の手順を使用して評価されます。

  • まず、配列参照式が評価されます。この評価が突然完了すると、同じ理由で配列アクセスが突然完了し、インデックス式は評価されません。

  • それ以外の場合は、インデックス式が評価されます。この評価が突然完了すると、同じ理由でアレイアクセスが突然完了します。

  • それ以外の場合、配列参照式の値が、の場合、nullaNullPointerExceptionがスローされます。

  • それ以外の場合、配列参照式の値は実際に配列を参照します。インデックス式の値がゼロ未満、または配列の値以上の場合length、anArrayIndexOutOfBoundsExceptionがスローされます。

  • それ以外の場合、配列アクセスの結果は、インデックス式の値によって選択された、配列内のタイプTの変数になります。


ここで、結果を理解するには、Java多次元配列が本質的にギザギザであり、配列の配列として実装されていることを理解する必要があります。anint[][]は単なる配列ですint[]

手元の真の式には、2つの配列アクセス式が含まれます。つまり、インデックス式がである外部配列アクセス式i++と、配列参照式自体が配列アクセス式です。つまり、参照式がgetArray()であり、インデックス式がですi++

評価のルールに従って、式を評価するgetArray()[i++][i++]には、最初に配列参照式を評価する必要がありgetArray()[i++]ます。結局のところ、これはそれ自体が配列のアクセスと式であり、同じルールを適用する必要があります。getArray()で結果を評価しnullます。インデックス式も、この時点でaがスローされるステップに到達する前に、i++完全に完了します(インクリメント)。外部配列アクセス式の配列参照式が突然終了したため、外部アクセス式のインデックス式()は評価されず、意味は1回だけインクリメントされます。iNullPointerExceptioni++i

...そして今あなたは知っています;-)

于 2012-08-22T05:11:01.127 に答える