【问题标题】:Java has (apparently) contradictory scopingJava 有(显然)矛盾的作用域
【发布时间】:2018-12-05 13:39:35
【问题描述】:

对于这个代码示例,Java 编译器并不满意:

public class Test1 {
  public static void main(String args[]) {
    int x = 99;
    {
      int x = 10;
      System.out.println(x);
    }
    System.out.println(x);
  }
}

编译器说:

错误:变量 x 已在方法 main(String[]) 中定义

不过,Java 编译器对此完全满意:

public class Test1 {
  public static void main(String args[]) {
    {
      int x = 10;
      System.out.println(x);
    }
    int x = 99;
    System.out.println(x);
  }
}

这在 Java 中有点疯狂。当我查看 Java 范围规则时,我几乎总是看到作者描述变量的范围在它们所在的块级别内,除了在实例生命周期内保留其值的对象级变量的实例。

它们都没有以解释 Java 编译器处理此处代码示例的方式来解释规则。但正如我们从这两个明显的例子中看到的那样,范围规则并没有像每个人描述的那样真正起作用。

请有人正确解释一下,以便我正确理解它吗?

【问题讨论】:

  • 内部块级别存在于外部范围级别,它已经​​具有 int(在第一种情况下),在第二种情况下,外部范围级别没有 int(还没有)。
  • 不,不。它工作得很好,你可以从内部看到外部,但不能从外部看到内部,就是这样
  • 要添加到下面的答案,还有什么替代方法?您似乎认为在第一个示例中,变量 x 的外部定义不应该从内部代码块中可见。
  • 对我来说——我的期望是两个代码示例都能很好地编译——即,“内部 x”只是一个完全不同于外部 x 的变量(不管事实如何另一个名为“x”的变量已在外部范围中定义),并且内部块中对“x”的任何引用都是对“内部x”的引用。另一方面,在编译器抱怨我的第一个示例(这是一个从我目前正在处理的更大程序中大量简化的示例)之后,我对编译器接受第二个示例感到相当惊讶。我明白了——但我觉得这很不和谐。
  • 它没有什么奇怪或独特之处。范围约束不是双向的。如果一个作用域嵌套在另一个作用域中,则子作用域会从父作用域继承可见性,反之则不然。

标签: java scope


【解决方案1】:
int x = 99;
{
  int x = 10;   // variable x defined before is still available, so you can not define it again
  System.out.println(x);
}
System.out.println(x);

还有:

{
  int x = 10;
  System.out.println(x);
}
int x = 99;    // variable x defined before is not available, so you can define it again
System.out.println(x);

【讨论】:

    【解决方案2】:

    我可以尝试解释,但不知道确切的规则。

    在第一个示例中,x 在内部范围内都是已知的。这是不允许的。

    在第二个示例中,在内部范围内,外部x 尚未定义。所以没有问题。

    【讨论】:

      【解决方案3】:
      public class Test1 {
        public static void main(String args[]) {
          int x = 99;
          {
            int x = 10; // not allowed because the fist x is visible/known here
            System.out.println(x);
          }
          System.out.println(x);
        }
      }
      

      第一个代码中第一个x的作用域在main方法内 所以x 在方法中随处可见,这就是为什么它不允许 重新声明它。

      在第二个代码中,第一个 x 的范围在块 {} 内 因此,由于在此块之外 x 不可见或未知,因此允许声明第二个 x

      public class Test1 {
        public static void main(String args[]) {
          {
            int x = 10;
            System.out.println(x);
          // x gets out of scope after this closing block
          }
          int x = 99;  // allowed because the first x got out of scope
          System.out.println(x);
        }
      }
      

      【讨论】:

        【解决方案4】:

        这不是 Java 的问题。声明并使用第二个 x 时,作用域变量 x 已超出作用域。

        【讨论】:

        • 显然这个简短的回答不足以真正回答问题
        猜你喜欢
        • 1970-01-01
        • 2023-03-10
        • 1970-01-01
        • 1970-01-01
        • 2017-03-09
        • 2011-02-03
        • 1970-01-01
        • 2017-11-06
        • 2016-02-21
        相关资源
        最近更新 更多