为何Java禁止int a=a这类遮蔽赋值,却允许间接赋值写法?
Java变量声明与作用域规则解析
为什么第一段代码不合法?
看这段代码:
class A { int a; void foo() { int a = a; } }
当你写int a = a;时,Java编译器会把右边的a认定为刚刚声明的这个局部变量——因为局部变量的作用域从它的标识符出现那一刻就开始了,会直接遮蔽掉类里的成员变量a。但问题是,这个局部变量此时还没完成初始化,Java明确禁止使用未初始化的局部变量,所以编译器会直接报错。
第二段代码为什么合法?
再看这段:
class A { int a; void foo() { int b = a; int a = b; } }
- 第一行
int b = a;:此时局部变量a还没声明,编译器会往上查找作用域,找到类的成员变量a(成员变量会默认初始化,int类型默认值为0),所以b能正常拿到值,这一步完全合法。 - 第二行
int a = b;:现在声明局部变量a,右边的b已经完成初始化,用它给新的局部a赋值符合Java的变量使用规则,自然合法。
Java的明确规则说明
Java语言规范里对这类场景有明确规定:
- 局部变量的作用域从其声明语句中标识符出现的位置开始,到所在代码块结束为止。在声明语句里引用该变量时,它已经“被声明”但未“完成初始化”,而Java要求局部变量必须显式初始化后才能被使用。
- 当局部变量和成员变量同名时,局部变量会遮蔽成员变量,但只有当局部变量进入作用域之后,这种遮蔽才会生效。
和C不同的是,C的作用域规则允许这类容易混淆的写法(比如int a = a;可能会引用外部作用域的变量,甚至某些场景下允许使用未初始化的变量,尽管这属于不良编码实践),但Java的规则更严格,目的就是避免这种容易引发错误的模糊场景。
内容的提问来源于stack exchange,提问作者user129393192
相关产品推荐
相关产品推荐

