为什么这个Java代码会编译?

时间:2013-04-04 09:19:17

标签: java compiler-construction

在方法或类范围中,下面的行编译(带警告):

int x = x = 1;

在类范围中,变量获取默认值,以下内容给出了“未定义引用”错误:

int x = x + 1;

是不是第一个x = x = 1最终会出现相同的“未定义引用”错误?或者第二行int x = x + 1应该编译?或者有一些我想念的东西?

13 个答案:

答案 0 :(得分:86)

int x = x = 1;

相当于

int x = 1;
x = x; //warning here

int x = x + 1; 

首先我们需要计算x+1但是x的值是未知的,所以你得到一个错误(编译器知道x的值是未知的)

答案 1 :(得分:41)

大致相当于:

int x;
x = 1;
x = 1;

首先,int <var> = <expression>;始终等同于

int <var>;
<var> = <expression>;

在这种情况下,您的表达式为x = 1,这也是一个声明。 x = 1是一个有效的语句,因为已经声明了var x。它也是值为1的表达式,然后再次分配给x

答案 2 :(得分:12)

在java或任何现代语言中,赋值来自右侧。

假设您有两个变量x和y,

int z = x = y = 5;

此语句有效,这是编译器分割它们的方式。

y = 5;
x = y;
z = x; // which will be 5

但在你的情况下

int x = x + 1;

编译器给出了一个例外,因为它会像这样分裂。

x = 1; // oops, it isn't declared because assignment comes from the right.

答案 3 :(得分:8)

int x = x = 1;不等于:

int x;
x = 1;
x = x;

javap再次帮助我们,这些是为此代码生成的JVM指令:

0: iconst_1    //load constant to stack
1: dup         //duplicate it
2: istore_1    //set x to constant
3: istore_1    //set x to constant

更像是:

int x = 1;
x = 1;

这里没有理由抛出未定义的引用错误。现在在它的初始化之前使用变量,因此该代码完全符合规范。 实际上根本没有使用变量,只是分配。而且JIT编译器会更进一步,它将消除这种结构。说实话,我不明白这段代码是如何与JLS的变量初始化和使用规范相关联的。没用就没问题。 ;)

如果我错了,请更正。我无法弄清楚为什么其他答案,涉及许多JLS段落收集了这么多的优点。这些段落与本案没有任何共同之处。只需两个连续作业即可。

如果我们写:

int b, c, d, e, f;
int a = b = c = d = e = f = 5;

等于:

f = 5
e = 5
d = 5
c = 5
b = 5
a = 5

最右边的表达式只是逐个分配给变量,没有任何递归。我们可以以任何方式混淆变量:

a = b = c = f = e = d = a = a = a = a = a = e = f = 5;

答案 4 :(得分:7)

int x = x + 1;中,您向x添加1,那么x的值是多少,它尚未创建。

但是在int x=x=1;中编译时没有错误,因为您将1分配给x

答案 5 :(得分:5)

您的第一段代码包含第二段=而不是加号。这将在任何地方编译,而第二段代码不会在任何一个地方编译。

答案 6 :(得分:5)

在第二段代码中,x在声明之前使用,而在第一段代码中,它只被分配了两次,没有意义但是有效。

答案 7 :(得分:5)

让我们一步一步地分解,正确的联想

int x = x = 1

x = 1,将1分配给变量x

int x = x,将x指定为自身,作为int。由于x以前被指定为1,因此它保留1,尽管是多余的。

编译好。

int x = x + 1

x + 1,将一个添加到变量x。但是,x未定义,这将导致编译错误。

int x = x + 1,因此这行编译错误,因为equals的右边部分不会编译,将一个添加到未分配的变量

答案 8 :(得分:3)

第二个int x=x=1是编译因为你将值赋给x但是在其他情况下int x=x+1这里变量x没有被初始化,记住在java局部变量中没有初始化为默认值。 注意如果在类范围内它(int x=x+1)也会因为未创建变量而产生编译错误。

答案 9 :(得分:2)

int x = x + 1;

在Visual Studio 2008中成功编译并发出警告

warning C4700: uninitialized local variable 'x' used`

答案 10 :(得分:2)

x未在x = x + 1;中初始化。

Java编程语言是静态类型的,这意味着必须首先声明所有变量才能使用它们。

请参阅primitive data types

答案 11 :(得分:2)

由于代码的实际工作方式,代码行无法编译并发出警告。 运行代码int x = x = 1时,Java首先按照定义创建变量x然后它会运行分配代码(x = 1)。由于已定义x,因此系统没有错误将x设置为1.这将返回值1,因为现在是x的值。因此,x现在最终设为1.
Java基本上执行代码,就像这样:

int x;
x = (x = 1); // (x = 1) returns 1 so there is no error

但是,在您的第二段代码int x = x + 1中,+ 1语句需要定义x,到那时它不是。{1}}。由于赋值语句始终意味着首先运行=右侧的代码,因此代码将失败,因为x未定义。 Java将运行如下代码:

int x;
x = x + 1; // this line causes the error because `x` is undefined

答案 12 :(得分:-1)

编译器从右到左阅读语句,我们的目的是做相反的事情。这就是为什么它一开始很恼火。从右到左让这个习惯读取语句(代码),你就不会遇到这样的问题。