本地变量作用域和for循环

4

我刚开始学习Java。我有一些初级问题。我不是很明白为什么在这种情况下:

int j = 5;
for (int j = 0; j < 10; j++) {
   // do sth
}

我的编译器显示:“j变量在作用域中已经定义”。为什么第二个j会有问题?我认为它应该只是遮盖了第一个。

你能把整个异常信息粘贴过来吗? - pepuch
2
我认为它应该只是简单地遮蔽第一个。但实际上并不是这样的。在Java中没有变量遮蔽。 - Cephalopod
你不需要在for(...)循环内部声明j。 - Arun Manjhi
问题是当您在同一作用域中定义了两个相同的变量时,编译器无法确定哪一个是有效的。 - user902383
1
你希望编译器如何知道你在循环内引用的是哪个 j - Maroun
8个回答

6
问题在于您声明了变量j两次:一次在for循环外部,一次在内部。只需删除上面的那行代码,您就可以继续了。
本地变量不会被遮蔽 - 也许您考虑到了字段(但这与您此处的情况不同)。

4
一个更简单但类似的场景是:
int i = 0;
{
   int i = 2;
}

所以你有两个i变量。当你引用i时,你指的是哪一个?

Java编译器不允许在这里进行“遮蔽”。定义是模糊的,编译器正在警告你。


3
请参考Java语言规范第6.4节了解有关阴影和遮蔽的规则。他们甚至提供了相同的例子:

由于将标识符声明为方法、构造函数或初始化块的局部变量不能出现在具有相同名称的参数或局部变量的作用域内,因此以下程序会出现编译时错误:

class Test1 {
    public static void main(String[] args) {
        int i;
        for (int i = 0; i < 10; i++)
            System.out.println(i);
    }
}

该限制有助于检测其他非常难以发现的错误。对成员变量被本地变量遮盖进行类似的限制是不切实际的,因为在超类中添加成员变量可能会导致子类必须重新命名本地变量。相关考虑也使得对嵌套类的成员变量遮盖本地变量或在嵌套类内声明的本地变量被本地变量遮盖的限制变得不太吸引人。

2
这样说吧。如果你被允许在for循环中声明变量 i ,那么如何引用在 for 循环之前声明的局部变量 i ?您无法使用任何合格的名称来执行此操作,而简单的名称将引用for循环变量。这就是为什么不允许的原因。
该行为如JLS中所列出。从 JLS - 第6.4节

局部变量(§14.4),形式参数(§8.4.1),异常参数(§14.20)和本地类(§14.3)只能使用简单名称(§6.2)而不是限定名称(§6.6)。

某些声明不允许在局部变量、形式参数、异常参数或本地类声明的范围内,因为使用简单名称就无法区分已声明的实体。

并从 JLS - 第6.3节中可以了解到以下信息:

块(§14.4)中的局部变量声明的作用域是在该声明中出现的块的其余部分,从其自己的初始化程序开始,并包括在本地变量声明语句中向右的任何进一步声明器。

再次强调。
在JLS第6.4节中,指定在相同范围内重新声明局部变量将导致编译时错误:

如果局部变量v的名称作为v的直接封闭方法、构造函数或初始化器块的局部变量重新声明,在v的范围内作为try语句中catch子句的异常参数,在v的范围内作为try-with-resources语句中的资源,则编译时错误。


0
Cause this is a duplicate local variable problem, You already define "j" variable before. Try this:

                int i = 5;
        for (int j = 0; j < 10; j++) {
           // do sth
        }

0
 int j = 5; // this j is visible to whole method 
 for (int j = 0; j < 10; j++) { 
      // so still j is visible to this for loop and you can use it 
      // but you can't initialize it again
 // do sth
 }

0
你已经声明了变量j两次。请按以下方式重写您的代码:
for (int j = 0; j < 10; j++) {
   // do sth
}

int j;
for (j = 0; j < 10; j++) {
   // do sth
}

0

只有当其中一个变量是方法字段,另一个变量是局部变量时才会发生遮蔽。在您的情况下,两者都是局部变量,因此它们不能相互遮蔽。

如果两个局部变量共享作用域,则不能具有相同名称,就像不能具有相同名称的两个字段一样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接