为什么 x 没有在这里初始化?
Why is x not initialized in this?
为什么下面的x没有初始化?
public class rough {
public static void main(String[] args) {
int x;
boolean found = false;
for (int i = 0; i < 10; i++) {
if (Math.random() < 0.5) {
found = true;
x = 10;
break;
}
}
if (!found)
x = -1;
System.out.println(x);//x isn't initialized here
}
}
平均而言,对于一半的迭代,for 循环内的 if
将是 true
,因此初始化 x
。对于另一半,found
保持 false
因此外部 if
将初始化。因此,我不明白为什么编译器会生气。
作为最终的蒸馏(见下面的连续简化),考虑
public static void main(String[] args) {
int x;
boolean found = false;
if (!found)
x = -1;
System.out.println(x);
}
这也给出了 x
不是 init 的错误。
之前的简化
更令人惊讶的是,改变
if (Math.random() < 0.5)
到if(true)
也有同样的问题
事实上,进一步调查,将原来的for
循环替换为这些
for (int i=0;i<1;i++)
x = 10;
for (; !found; ) {
x = 10;
break;
}
同样更糟。只有 for(;;){... break;}
& for(;true;){... break;}
不引发任何初始化。错误。
编译器无法轻松检测到所有导致 x
被初始化的分支,但是您可以通过将 -1
分配给 x
来很容易地修复它(和代码)首先。像
public static void main(String[] args) {
int x = -1;
for (int i = 0; i < 10; i++) {
if (Math.random() < 0.5) {
x = 10;
break;
}
}
System.out.println(x);
}
现在你不需要 found
(所以我也删除了它)。
(将其写成一个单独的答案,因为我认为从评论中删除它会受益)。
这是语言律师的回答。
变量使用前的语言规范requires initialization。
规则包括:
必须在代码的所有可能路径上为变量赋值。规范将其称为 'definite assignment'.
编译器在此分析中不考虑表达式的值。请参见示例 16.2。
第二条规则解释了为什么即使在对我们来说 'obvious' 的情况下,编译器也无法使用该知识。即使编译器编写者愿意做更深入的分析,遵守 Java 规范也不允许这样做。
如果下一个问题是 'but why?' 那么我不得不猜测,但标准的重点是获得一致的行为。您不希望一个编译器接受另一个编译器拒绝的东西是合法的 Java。
为什么下面的x没有初始化?
public class rough {
public static void main(String[] args) {
int x;
boolean found = false;
for (int i = 0; i < 10; i++) {
if (Math.random() < 0.5) {
found = true;
x = 10;
break;
}
}
if (!found)
x = -1;
System.out.println(x);//x isn't initialized here
}
}
平均而言,对于一半的迭代,for 循环内的 if
将是 true
,因此初始化 x
。对于另一半,found
保持 false
因此外部 if
将初始化。因此,我不明白为什么编译器会生气。
作为最终的蒸馏(见下面的连续简化),考虑
public static void main(String[] args) {
int x;
boolean found = false;
if (!found)
x = -1;
System.out.println(x);
}
这也给出了 x
不是 init 的错误。
之前的简化
更令人惊讶的是,改变
if (Math.random() < 0.5)
到if(true)
也有同样的问题
事实上,进一步调查,将原来的for
循环替换为这些
for (int i=0;i<1;i++)
x = 10;
for (; !found; ) {
x = 10;
break;
}
同样更糟。只有 for(;;){... break;}
& for(;true;){... break;}
不引发任何初始化。错误。
编译器无法轻松检测到所有导致 x
被初始化的分支,但是您可以通过将 -1
分配给 x
来很容易地修复它(和代码)首先。像
public static void main(String[] args) {
int x = -1;
for (int i = 0; i < 10; i++) {
if (Math.random() < 0.5) {
x = 10;
break;
}
}
System.out.println(x);
}
现在你不需要 found
(所以我也删除了它)。
(将其写成一个单独的答案,因为我认为从评论中删除它会受益)。
这是语言律师的回答。
变量使用前的语言规范requires initialization。
规则包括:
必须在代码的所有可能路径上为变量赋值。规范将其称为 'definite assignment'.
编译器在此分析中不考虑表达式的值。请参见示例 16.2。
第二条规则解释了为什么即使在对我们来说 'obvious' 的情况下,编译器也无法使用该知识。即使编译器编写者愿意做更深入的分析,遵守 Java 规范也不允许这样做。
如果下一个问题是 'but why?' 那么我不得不猜测,但标准的重点是获得一致的行为。您不希望一个编译器接受另一个编译器拒绝的东西是合法的 Java。