【发布时间】:2023-03-10 05:14:02
【问题描述】:
class Test {
int a;
void method() {
a = 1;
int a = a = 2;
a = 3;
}
}
method 中有很多 as。他们都指的是什么?
【问题讨论】:
标签: java language-lawyer language-specifications
class Test {
int a;
void method() {
a = 1;
int a = a = 2;
a = 3;
}
}
method 中有很多 as。他们都指的是什么?
【问题讨论】:
标签: java language-lawyer language-specifications
这是一个简单的例子,说明 Java 范围规则的奇异性。
a = 1;
int a = a = 2;
a = 3;
逐行分解:
a = 1; 指的是成员变量。a = 3; 指的是局部变量,因为它在局部变量的声明之后。您可以通过相同的标识符以相同的方法引用两个不同的符号,这非常令人困惑。int a = a = 2;:第二个a 是局部变量。变量声明中的自引用真的很好奇。你可以找到这个in the language spec:
- 块中局部变量声明的范围(第 14.4 节)是该声明出现的块的其余部分,从它自己的初始化程序开始,并在右侧包括任何进一步的声明符局部变量声明语句。
成员变量也可以在自己的初始化器中引用自己;但这是出于稍微不同的原因:
- 在类类型 C(第 8.1.6 节)中声明或继承的成员 m 的声明范围是 C 的整个主体,包括任何嵌套类型声明。
我还没有找到一个令人信服的理由来证明这个局部变量规则的存在;也许您只是真的想确保它已分配。我认为它允许您做的唯一一件事就是在初始化器的评估中将变量用作临时存储,例如:
int a = method(a = somethingThatIsReallyExpensiveToCompute(), a);
相当于:
int a;
{
int tmp = somethingThatIsReallyExpensiveToCompute();
a = method(tmp, tmp);
}
就我个人而言,我宁愿看代码的第二种形式,因为第一种形式的评估似乎很模糊。
【讨论】:
int a = a; 是一个有效的语句,即当外部作用域中有另一个 a 时,就像在你的例子中一样。现在,如果这不是晦涩难懂的话……
int a = a = 2; 可以分解为:int a = (a = 2);,然后是 int a; a = 2; a = a;