Java中的赋值运算符解释

5
public class Conversions {

        public static void main(String[] args) {

                    int index = 3;
                    int[] arr = new int[] { 10, 20, 30, 40};

                    arr[index] = index = 2; //(1)
                    System.out.println("" + arr[3] + " " + arr[2]);

            }
    }

我有这个,它会给出:

2 30 

I was hoping it will give

40 2

为什么在赋值时索引的值没有改为2而是保持为3?

(1)
3个回答

11

Java语言规范(JLS)第15.26节所暗示的=的右结合性意味着您的表达式可以表示为一棵,因此:

右结合性

           =
    +------+-------+
    |              |
arr[index]         =
              +----+----+
              |         |
            index       2

但是,第15.7节 表示:

Java编程语言保证运算符的操作数按照特定的顺序进行评估,即从左到右。

因此,在更新 index 的值之前,即在 index = 2 之前,将评估 arr[index]


显然,你不应该编写依赖于这个事实的代码,因为它依赖于几乎没有读者理解的规则。


@OliCharlesworth,在Java中并不是赋值语句左侧(left side)的问题。在那里它肯定不像一个表达式那样工作。 - zch
@zch:有点像。但是你回答中的引用确实将其描述为表达式... - Oliver Charlesworth
换句话说,永远不要因为使用括号而感到羞耻。 - Hot Licks
@HotLicks:我觉得括号并不能帮助楼主得到他们期望的答案... - Oliver Charlesworth
我说得过火了,说它不是表达式,我的意思是它从未被评估为表达式(如15.13.1所述)。对于无意义的讨论感到抱歉。 - zch
显示剩余2条评论

5
Java语言规范:15.26.1. 简单赋值操作符 =
如果左操作数是一个数组访问表达式(§15.13),可能被一个或多个括号包含,则:
- 首先,将计算左操作数数组访问表达式的数组引用子表达式。如果此计算突然完成,则出于同样的原因,赋值表达式也会突然完成;不计算左操作数数组访问表达式的索引子表达式和右操作数,并且不进行任何赋值。 - 否则,将计算左操作数数组访问表达式的索引子表达式。如果此计算突然完成,则出于同样的原因,赋值表达式也会突然完成,并且不计算右操作数,不进行赋值。 - 否则,将评估右操作数。如果此评估突然完成,则出于相同的原因,赋值表达式也会突然完成,并且不进行赋值。

[...](进一步的步骤已经解释)

正如您看到的那样,在赋值之前,先计算索引。

1
  1. 首先评估数组索引标头,以确定赋值的适当位置(arr[index])。
  2. 接下来评估所有后续运算符的优先级,并发现它们相等(所有运算符都是赋值运算符,因此具有相同的优先级)。
  3. 然后根据结合性评估操作数,对于赋值运算符而言,结合性是从右到左。

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