首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >何时在表达式中评估/返回/获取Java变量中的值?

何时在表达式中评估/返回/获取Java变量中的值?
EN

Stack Overflow用户
提问于 2016-10-07 20:53:49
回答 4查看 347关注 0票数 2

http://introcs.cs.princeton.edu/java/11precedence/认为,增量后算子比加法算子具有更高的优先级.

因此,对于以下代码:

代码语言:javascript
复制
    int i = 1;
    int j = i + i++;
    System.out.println(j);

我认为分配给j的表达式将按以下方式进行计算(每一行都是计算中的“步骤”):

代码语言:javascript
复制
   i + i++
   i + (1)   // do post-increment operator; returns 1, and makes i = 2
   (2) + (1)   // do addition operator. need to get the operand i, so do that.
   3

但是当我尝试这个程序时,j的值是2。

所以我很困惑。在表达式中,它是否将表达式中的所有“i”替换为当前值i,甚至在触摸i++之前?

编辑:这里的人使用的短语“评估顺序”帮助我找到了以下可能有用的堆栈溢出答案:Java中计算顺序的规则是什么?

编辑:我对下面的答案做了最好的猜测。我仍然欢迎对它的修正。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-10-24 13:51:10

编辑:我不完全理解别人给出的答案,但这是我对正在发生的事情最好的猜测。如果有人想纠正这一猜测,请这样做。

我的最佳猜测是:a + b * c (其中a、b和c是变量)被构造成表达式树,其中优先级最低的操作符位于树的顶部:

代码语言:javascript
复制
    +
  /   \
 a     *
      / \
     b    c

现在,对这棵树的求值方式如下:+操作符得到求值。为此,它(递归)计算左子树及其右子树,然后添加这些值。

总的来说,这就是所发生的事情:

代码语言:javascript
复制
  - addition operator gets evaluated.
    it says "evaluate my left subtree, then my right subtree,
    then add them together. i return that value"
        - left subtree: is a. evaluate variable a into a value.
          (that is, get the value of variable a.)
        - right subtree: i'm a multiplication operator. to evaluate me,
          evaluate my left subtree, then my right subtree, the nmultiply
          them togeter. i return that value.
                - left subtree: is variable b. evalute that.
                - right subtree: is variable c. evaluate that.

这就是为什么a首先完成其评估,然后是b,然后是c,然后是b * c,然后是a + (b * c)

在带有++i的表达式中,也会发生同样的事情。例如,对于++i + i++,表达式树如下所示:

代码语言:javascript
复制
          +
         / \
    preinc  postinc
       |      |  
       i      i

其中(例如) preinc指的是增量前运算符(而预增量运算符恰好有一个操作数:变量)。这里的区别是,当以preinc作为根的子树需要得到计算时,“计算preinc运算符树”并不意味着“用变量的值替换变量”(例如,2+ i ),而是意味着“在变量i中增加值,然后preinc(i)的值是变量i中的新值”。

以类似的方式,赋值运算符=的工作方式与2+ i略有不同。

代码语言:javascript
复制
    int j;
    j = 3;

这里的表达式树是

代码语言:javascript
复制
        =
       / \
      j   3

当一棵以赋值操作符作为根的树需要被求值时,这意味着“左手操作符必须是一个变量--而不是一个值!然后计算右边的子树(我们期望它将它求值为一个值),然后将该值放在左子树中的变量中。现在,由=(j,3)返回的值是右边子树中的值”。

有了这个猜测,我就能够正确地给出(链接为:https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.7)中给出的例子的答案。

也就是说,如果我绘制表达式树,下面两个示例是可以由我解决的:

示例:

代码语言:javascript
复制
  int i = 2;
  int j = (i = 3) * i;
  System.out.println(j);

示例:

代码语言:javascript
复制
  int b = 9;
  b = b + (b = 3);
  System.out.println(b);
票数 0
EN

Stack Overflow用户

发布于 2016-10-07 21:10:09

根据Java语言规范,15.7.1

在计算右操作数的任何部分之前,二进制运算符的左操作数似乎是完全计算的。

因此,加法运算符左侧的i将在右侧的i++之前进行计算。

票数 2
EN

Stack Overflow用户

发布于 2016-10-07 21:26:32

Post增量--首先使用以前的变量值,然后使用增量。

预增量-首先递增,然后使用新的变量值。

代码语言:javascript
复制
int i = 1;
int j = i + i++;
System.out.println(j);// 2
System.out.println(i);// 2

在这里,我首先用先前的i值i,e,e,+替换,再用i的旧值,这样j就变成2,然后我被增加到2。

现在考虑一下下面的代码

代码语言:javascript
复制
int i = 1;
int j = i++ + ++i;
System.out.println(j);// 4
System.out.println(i);// 3

在这里,首先我是增量(预),所以我变成2,然后我被取代,e,j=2+2,现在j值将是4,再一次我增加(post) 1,所以我的当前值是3。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39925647

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档