我在官方java教程中写了一个简单的“在多维数组中查找数字”。这是教程中包含的代码:
class LabeledBreak {
public static void main(String[] args) {
int [][] numbers = {
{22, 34, 675, 23, 23},
{34, 76, 98, 23, 11},
{65, 234, 87, 23, 76}
};
int searchFor = 123;
boolean found = false;
int i;
int j = 0; // <-- this line
search:
for (i = 0; i < numbers.length; i++) {
for (j = 0; j < numbers[i].length; j++) {
if (searchFor == numbers[i][j]) {
found = true;
break search;
}
}
}
if (found == true)
System.out.println("Found " + searchFor + " at index " + i + ", " + j);
else
System.out.println(searchFor + " not found!!!");
}
我无法理解这里初始化“j”的重点是什么。我尝试删除初始化语句,并使其只是一个声明。但我得到了这个错误:
“变量j可能尚未初始化”
为什么我要初始化“j”?为什么“i”也不需要初始化?
答案 0 :(得分:11)
好吧,如果numbers.length
为0,则内循环永远不会运行,因此永远不会初始化j
,即你永远不会到达j = 0;
语句。
答案 1 :(得分:2)
我无法将其纳入评论,因此我已将代码放在此处。
恕我直言,最好使用不会遇到这些问题的结构。
FOUND: {
for (int i = 0; i < numbers.length; i++)
for (int j = 0; j < numbers[i].length; j++)
if (searchFor == numbers[i][j]) {
System.out.println("Found "+searchFor+" at index "+i+", "+j);
break FOUND;
}
System.out.println(searchFor + " not found!!!");
}
变量的范围仅限于安全使用的范围。
答案 2 :(得分:1)
考虑以下代码:
int j = 1234567;
int end = -100;
for (int i = 0; i < end; i++)
for (j = 0; j < 10; j++)
System.println("Hello.");
System.println("j is "+j);
尝试end
的不同值。请注意输出为1234567
。
答案 3 :(得分:0)
为什么Java会关注禁止读取未初始化的变量?
此类代码构造往往是非确定性的,因此难以调试,因此不可靠。此外,不加选择的堆栈内存重用可能导致安全漏洞。
Java语言规范,第16节,定义了什么使变量“在使用前明确分配”,主要是通过查看代码流(语法结构),但忽略其他变量的内容,即使已知,并忽略了确切的方法是什么一路上叫。
但我总是初始化j
。
是的,你这样做。但要证明这一点,您需要深入了解numbers
的初始内容,了解length
方法的工作原理,甚至排除其他线程获取对{{1}的引用的可能性。并在主线程执行时修改数组。
但在设置numbers
时,我不会在代码路径之外访问j
,因此found
已初始化。
正如你所说。但是JLS第16节只考虑代码结构,而不考虑其他变量的值,例如`j
。
为什么found
有所不同?
i
的初始化纯粹在语法上保证是在外部循环中发生的第一件事,即使它的主体(纯粹是假设的)根本不执行。
如果我的Java编译器足够聪明,看不到我没有访问任何未初始化的变量怎么办?
就JLS第16节而言,这并没有改变任何东西。您的编译器不允许您保存这样的形式化初始化器,因为该程序可能无法移植到可能不同样智能的其他Java编译器。