【问题标题】:Compiler Understanding - assign in a if statement编译器理解 - 在 if 语句中赋值
【发布时间】:2014-11-26 23:08:30
【问题描述】:

我最近遇到了这种语法

int i;
String s = "test";
if(!((i=s.length()) == 0)) {
    System.out.println(i);
}

如果您想知道它打印的是什么:

4

现在我知道这段代码可以正确编译和运行。我也明白这会将 s.length 的值放入 i 中。我想知道这怎么可能? 我们如何在 if 子句中等同/分配变量。是否有人对编译器如何工作有任何见解

【问题讨论】:

  • 在 C、Java 和许多其他语言中,a = 5; 等赋值被视为“表达式”,因此具有值。您偶尔会看到,例如,a = b = c = 5; 将一堆变量初始化为相同的值。
  • 而在某些环境下你会看到类似while (GOOD_RETURN_CODE == returnCode = someFunction(someParms)) { ...的东西,所以someFunction的returnCode可以保存并在一次操作中检查。对于while 语句,这避免了一些尴尬的代码。

标签: java if-statement assign


【解决方案1】:

Java 编译器在某种堆栈解析器上运行,它从左到右计算每一行。每当遇到右括号时,返回最后一个左括号的前一个语句将在其他任何事情之前执行,所以......

最里面的括号将在其他任何东西之前被评估,当然是 (i=s.length())。

我现在不在我的主计算机上,所以我无法真正测试这个,但我相信如果你删除 i=s.length() 周围的括号,你会收到语法错误。

【讨论】:

    【解决方案2】:

    赋值运算符是一个普通的表达式。
    像任何其他表达式一样,您可以将其放在任何您想要的位置。

    这个表达式的值就是被赋值的值。 (这也是为什么你可以写a = b = c

    【讨论】:

    • 我知道 a= b =c 但这更像是 a=b==c 现在这意味着 a==c 还是 b==c ?导致在这种情况下,在 a=b 之前没有分配 a ...
    • @wrongAnswer: == 的优先级高于=,因此解析为a = (b == c)
    • 感谢您的解释。永远不要欣赏它,尽管关于运算符优先级的内容会读到更多。
    • @Pshemo:我的意思是普通的。
    【解决方案3】:

    赋值表达式

    i=s.length()
    

    解析为被分配的值。

    From the JLS

    在运行时,赋值表达式的结果是 赋值后的变量。 赋值表达式本身不是变量。

    我现在不想去获取字节码,但基本上

    1. s 的值被压入堆栈
    2. 该值被弹出并取消引用以调用String#length()
    3. 结果被压入堆栈
    4. 再次将相同的结果压入堆栈
    5. 该值从堆栈中弹出并存储在i
    6. 0 的值(可能没有,因为可能有用于与 0 比较的字节码指令)被压入堆栈
    7. 值和 0 都从堆栈中弹出并比较,根据结果使用跳转指令

    【讨论】:

    • 运算符优先级与此有关吗? stackoverflow.com/a/26152736/1085186
    • @wrongAnswer 我认为 SLaks 指的是您的评论。在您的问题中,括号明确声明了表达式的分组。
    • 感谢您的解释。
    【解决方案4】:

    为了理解这一点,让我们尝试剖析它,每个语句的语句

    if(!((i=s.length()) == 0))
    s.length() //results to 4;
    i=s.length() //assigned i=4
    i=s.length() == 0 //false
    !i=s.length() == 0 //invert, becomes true
    if(true) {
        //prints i
    }
    

    【讨论】:

      【解决方案5】:

      Java 赋值的结果是赋值,也就是说这个

      (!((i=s.length()) == 0)) 
      

      s.length() 分配给i,然后检查该值(s.length()) 是否不是0

      【讨论】:

      • 我知道我难以理解的部分是它如何知道要与什么进行比较?因为我没有初始化。
      • @wrongAnswer ii=s.length() 初始化为s.length()
      • 请注意,尽管在这种情况下它是等效的,但 i 不会被重新评估以进行比较。
      猜你喜欢
      • 1970-01-01
      • 2015-07-15
      • 2010-11-27
      • 2011-10-30
      • 1970-01-01
      • 1970-01-01
      • 2020-01-20
      • 2014-07-19
      • 2020-08-07
      相关资源
      最近更新 更多