Java 变量[x]已在方法[y]中定义,但作用域不同
我不知道为什么这个代码不起作用。正如您所看到的,变量Java 变量[x]已在方法[y]中定义,但作用域不同,java,netbeans,scope,Java,Netbeans,Scope,我不知道为什么这个代码不起作用。正如您所看到的,变量x显然存在于两个地方,但它们在两个不同的范围内。在下面的示例中,它们位于两个不同的case语句中,第二个位于另一个if语句中。有什么好处?为什么会出现这样的错误,即变量“已定义”?最新的编译器和Netbeans。我习惯C++,这不是问题。谢谢 package testapp; public class TestApp { /** * @param args the command line arguments *
x
显然存在于两个地方,但它们在两个不同的范围内。在下面的示例中,它们位于两个不同的case
语句中,第二个位于另一个if
语句中。有什么好处?为什么会出现这样的错误,即变量“已定义”?最新的编译器和Netbeans。我习惯C++,这不是问题。谢谢
package testapp;
public class TestApp {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
int decisionValue1 = Integer.parseInt(System.console().readLine());
int decisionValue2 = Integer.parseInt(System.console().readLine());
switch (decisionValue1)
{
case 1:
int x = decisionValue1;
System.out.println(x);
break;
case 2:
if (decisionValue2 == 4)
{
int x = decisionValue2;
System.out.println(x);
}
break;
default:
break;
}
}
}
具体而言,错误是:
[Source Dir]: error: variable x is already defined in method main(String[])
编辑:
嘿,伙计们。由于最初的响应集中在switch
语句上,因此我在下面做了一个修改示例。没有switch
语句,但有相同的错误
public class TestApp {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
int decisionValue1 = Integer.parseInt(System.console().readLine());
int decisionValue2 = Integer.parseInt(System.console().readLine());
int x = decisionValue1;
if (decisionValue1 == 4)
{
int x = decisionValue2;
System.out.println(x);
}
}
}
因为
switch
语句不必break
,执行流可以继续到下一种情况,它们不在不同的范围内。第二个x
位于if
语句中的事实不会改变这一点,因为if
仍在开关中
当您添加第二个x
时,您将等效地执行以下操作:
+-------+
| x |
| +---+ |
| | x | |
| +---+ |
+-------+
如您所见,同一个框中有两个x
s(不允许)
在x
的第一个声明周围添加大括号:
case 1:
{
int x = decisionValue1;
System.out.println(x);
break;
}
将产生如下图片:
+-------+
| +---+ |
| | x | |
| +---+ |
| +---+ |
| | x | |
| +---+ |
+-------+
这是允许的。因为开关
语句不必中断
,执行流可以继续到下一种情况,它们不在不同的范围内。第二个x
位于if
语句中的事实不会改变这一点,因为if
仍在开关中
当您添加第二个x
时,您将等效地执行以下操作:
+-------+
| x |
| +---+ |
| | x | |
| +---+ |
+-------+
如您所见,同一个框中有两个x
s(不允许)
在x
的第一个声明周围添加大括号:
case 1:
{
int x = decisionValue1;
System.out.println(x);
break;
}
将产生如下图片:
+-------+
| +---+ |
| | x | |
| +---+ |
| +---+ |
| | x | |
| +---+ |
+-------+
这是允许的。这是因为两件事:
作用域是嵌套的
开关中的所有内容都在一个范围内——不同的情况并不重要
因此,开关在案例1
部分中声明一个intx
。然后,在案例2
部分中,您的if
块声明了一个嵌套的作用域,该作用域也尝试声明int x
,这是编译器不允许的
一种解决方案是在案例1
部分中放置一个“匿名块”。您可以将块放在可以放置语句的任何位置,它会创建自己的作用域:
case 1:
{ // anonymous scope
int x = ...
}
这样,开关中最外层的作用域不会声明intx
,您就可以了
有趣的是,这正是您的if
语句所发生的事情!如果(条件)
,则必须遵循的东西只是一个单独的语句;大多数情况下,该语句是一个块,但在这方面,该块as语句与代码中“随机”放置的任何语句没有区别。这是由于两个原因:
作用域是嵌套的
开关中的所有内容都在一个范围内——不同的情况并不重要
因此,开关在案例1
部分中声明一个intx
。然后,在案例2
部分中,您的if
块声明了一个嵌套的作用域,该作用域也尝试声明int x
,这是编译器不允许的
一种解决方案是在案例1
部分中放置一个“匿名块”。您可以将块放在可以放置语句的任何位置,它会创建自己的作用域:
case 1:
{ // anonymous scope
int x = ...
}
这样,开关中最外层的作用域不会声明intx
,您就可以了
有趣的是,这正是您的if
语句所发生的事情!如果(条件)
,则必须遵循的东西只是一个单独的语句;大多数情况下,该语句是一个块,但在这方面,该块作为语句与代码中“随机”放置的任何语句没有区别。您需要大括号来更改范围。类似的问题:@ChrisThompson不一定。范围可以在没有大括号的情况下更改(例如,一行if语句)。它们不在不相交的范围内。第一个x的范围是整个case语句。提示可能重复:用{}
包围案例1
的“主体”。您需要大括号来更改范围。类似的问题:@ChrisThompson不一定。范围可以在没有大括号的情况下更改(例如,一行if语句)。它们不在不相交的范围内。第一个x的范围是整个case语句。提示可能重复:用{}
包围案例1
的“主体”。谢谢。我可以理解,编译器可能没有足够的“聪明”来认识到最后有一个无条件的break语句——我可以接受这一点。但是,“if”语句确实创建了一个新的本地范围。。不是吗?或者这只是我不得不忍受的东西?。@phoenyx是的,但它嵌套在交换机的作用域中,声明int x
@phoenyx-Java不允许在同一局部作用域中使用相同名称的多个变量。谢谢大家。只是澄清一下,子作用域不会在Java中创建“新作用域”——这样子作用域(内方)中的引用只引用最里面的声明?我想你的例子就是这么说的。这不是在C++中的情况。令人惊讶的我还用一个“非切换”的例子编辑了我的原始问题。同样的结果,谢谢。我可以理解,编译器可能没有足够的“聪明”来认识到最后有一个无条件的break语句——我可以接受这一点。但是,“if”语句确实创建了一个新的本地范围。。不是吗?或者这只是我必须忍受的东西?@Phoenyx是的,但这是我的智慧