【问题标题】:Why don't java & js allow variable declaration in a condition为什么 java & js 不允许在条件中声明变量
【发布时间】:2017-01-09 01:16:27
【问题描述】:
 int a; // why can't I put this in the condition itself
 if((a = readData()) > 0){ 
     // do something..
 }

我想知道为什么 java 和 javascript 不允许我在 (condition) 中声明我的变量。我知道这与变量声明必须是第一件事有关-除了for循环-但根本原因是什么? In C++ it seems like they can do it。我不知道 C++,所以如果我误解了,我深表歉意。

【问题讨论】:

  • Java 与 Javascript 无关,而且该语言根本不允许您在 if 中声明变量。
  • @ElliottFrisch 我提到了这两种语言,因为这是我知道的两种语言,我希望它们的根本原因是相同的。抱歉,如果不清楚。我的问题是他们为什么不允许这样做?
  • 我想你需要问问 James Gosling 为什么他不包含它。 int a = readData(); if (a > 0) ... 有什么问题?它比试图在一行中塞进太多东西更具可读性。
  • @ajb 限制范围会很有用。
  • @shmosel {int a = readData(); if (a > 0) ... }

标签: java compiler-errors compilation


【解决方案1】:

原因是范围规则的简单性。如果您允许在条件中声明变量,则必须定义此类变量的范围,以及声明具有值意味着什么。两者都不是直截了当的。要求表达式中的变量已经定义很简单,而且没有缺点。允许这样做很复杂,并且会混淆来源。当然,这是后验推理。可能只是语言设计者当时有其他原因。

你为什么在乎?底线:因为 JLS 是这么说的。

【讨论】:

    【解决方案2】:

    根据 Java 语言规范 (https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.9),if 语句具有以下形式:

    if ( Expression ) Statement [else ...]
    

    变量赋值,又名AssignmentExpression,只是抽象Expression (https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.26) 的众多子类型之一,因此您可以使用它的结果(恰好是分配的值)在您的if 声明中。

    【讨论】:

      【解决方案3】:

      它的简单: If 语句被定义为:

      if (Boolean) {...
      

      我们现在可以替换:

      if (var1 operator var2){... // with "_ operator _" => Boolean
      

      如果我们现在将 i=1 设为 var1,我们会得到:

      if ((i=1) operator var2){... // compile error: i cannot resolved to a local variable
      

      int i = 1:

      if ((int i = 1) operator var2){...
      

      明显的问题是:int i = 1 是类型声明而不是变量,我们在上面了解到 if 子句只接受布尔变量或导致布尔变量的表达式...!

      【讨论】:

      • 我不认为这是一个答案。在我看来,您是在重申 OP 已经知道的内容。问题是,why 不允许这种语法,答案根本没有解决。
      【解决方案4】:

      我对这里的答案并不满意,所以像任何正常人一样,我学习了 java 字节码。嗯,有点……初级。因此,如果有人读到这篇文章,请记住我的发现有一些推断,并且可能不准确.. 然而,为什么它不会发生 java 是有道理的(更不用说在 javascript 中我的头在问这个问题时)而且它是何如此简单。


      现在是字节码部分:

      这是我得到的:

          int a = 9;
          System.out.println(a);  // just here to prevent some optimization
          if((a = 18) > 15){
              System.out.println(a);
          }
      
      
      Code:
         0: bipush        9
         2: istore_1
                                // -- removed the System.out.print -- 
        10: bipush        18
        12: dup
        13: istore_1
        14: bipush        15
        16: if_icmple     26
      

      会发生什么:

      0: push 9 onto the stack
      2: store it in the var a
      10: push 18 onto stack
      12: duplicate 18 on top of the stack
      13: store it in var a
      14 : push 15
      16: the if statement if value1 is less than or equal to value2, branch to instruction at branchoffset.
      

      因此,由于条件的内容是在 if 语句本身之前评估的,如果我们在条件中声明 int a,取决于我们定义 int a 的范围的位置,将会存在范围问题。


      如果它在 if 块内:

      如果我们假设 int a 将被限定在 if 块中,它仍然必须在到达它之前进行评估,因此超出了范围!

      换句话说:

      while((int a = 9) > 15)
      

      int a = 9 将在达到 while 条件之前进行评估,因此超出了我们刚刚定义的范围。我们不会进入 while 块,但是 a 的值是明确定义的!为什么它没有发生是有道理的,不是吗?


      如果我们反过来说这只是一个捷径:

       int a;
       while((a = 9) > 15)
      

      那么语言会不一致,会带来很多混乱的代码!请参阅for 循环,例如,其中定义的变量在其中而不是在外部范围内。

      它仍然没有任何意义,为什么它不可能在 javascript 中做。但是我并不在乎。

      我希望我说清楚了,至少它对我有一些意义,并且我学到了一些东西。在旁注中,我认为我的问题并不值得如此多的反对票,即使答案现在对我来说似乎很明显。并非关于 stackoverflow 的每个问题都必须是实际问题..

      【讨论】:

      • 您混淆了 3 个彼此无关的事物:范围、字节码和语法。对您问题的第一条评论是正确答案。
      猜你喜欢
      • 1970-01-01
      • 2015-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-10
      • 2015-09-22
      • 1970-01-01
      相关资源
      最近更新 更多