你们是否会在以下方面给我启发:
摘录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.
}
}
}
为什么变量i在第二个代码块中没有增加两次?
我错过了什么?
感谢。
答案 0 :(得分: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);
}
}
}
答案 1 :(得分:1)
如my comment中所述......
首先,重要的是要注意Java从左到右进行评估。我们发现getArray()[i++]
尝试访问被视为数组的null
元素,从而生成NullPointerException
。在计算外部数组访问表达式(其索引计算为getArray()[i++][i++]
)之前,此异常会中断对表达式i++
的求值,因此第二个增量永远不会发生: - )
这符合§15.13 of the Java Language Specification,它描述了数组访问表达式。
ArrayAccess: ExpressionName [ Expression ] PrimaryNoNewArray [ Expression ]
表达式评估的逐步程序在§15.13.1 Run-time Evaluation of Array Access中明确说明:
使用以下过程评估数组访问表达式:
首先,计算数组引用表达式。如果此评估突然完成,则数组访问会因同样的原因而突然完成,并且不会评估索引表达式。
否则,将评估索引表达式。如果此评估突然完成,则阵列访问会因同样的原因突然完成。
否则,如果数组引用表达式的值为
null
,则抛出NullPointerException
。否则,数组引用表达式的值确实是指数组。如果索引表达式的值小于零,或大于或等于数组的
length
,则抛出ArrayIndexOutOfBoundsException
。否则,数组访问的结果是数组中类型T的变量,由索引表达式的值选择。
现在,为了理解我们的结果,您必须意识到Java多维数组本质上是锯齿状的并实现为数组数组; int[][]
只是int[]
的数组。
手头的真实表达式涉及两个数组访问表达式,即一个外部数组访问表达式,其索引表达式为i++
,数组引用表达式本身就是一个数组访问表达式,即一个其引用表达式为getArray()
,其索引表达式为i++
。
遵循评估规则,为了评估表达式getArray()[i++][i++]
,我们首先必须评估数组引用表达式,即getArray()[i++]
。事实证明,这本身就是一个数组访问和表达式,我们必须应用相同的规则。评估getArray()
会产生null
。索引表达式i++
也完全完成(递增i
),然后到达此时抛出NullPointerException
的步骤。由于外部数组访问表达式的数组引用表达式突然结束,因此也不会评估外部访问表达式的索引表达式(i++
),这意味着i
仅递增一次。
......现在你知道了; - )