【问题标题】:Confusing while block阻塞时令人困惑
【发布时间】:2013-09-24 16:50:04
【问题描述】:

下面的代码块给了我一个编译时错误。

        while(false)
        {
          System.out.println("HI");
        }

错误表示存在无法访问的语句。 但是下面的代码编译

   boolean b=false;
   while(b)
   {
        System.out.println("Hi");
    }

我能想到的就是这个 -> 如果 case-1 as false 是一个文字,所以编译器发现它无法访问,如果在运行时检查 while 条件块中的 case 2 变量 b,那么就没有编译错误?

【问题讨论】:

    标签: java while-loop scjp


    【解决方案1】:

    编译器编写者无法决定将哪些条件标记为错误 - 规则在 Java 语言规范中,针对 14.21 Unreachable Statements 中的此问题。

    相关句子是:“当while语句可达且条件表达式不是值为假的常量表达式时,包含的语句是可达的。”

    在每种情况下,您都有一个可访问的 while 语句。在第一个版本中,false 是一个值为 false 的常量表达式,因此包含的语句不被认为是可达的。在第二个版本中,b 根本不是一个常量表达式,因此包含的语句被视为可访问的。

    b 的声明中添加final 会将while 条件更改为值为false 的常量表达式,从而使包含的语句再次无法访问。

    为 JLS 中的编译时错误和非编译时错误指定规则的好处是,所有 Java 编译器都应该接受相同的程序集。规则一般不要求编译器做数据流分析,大概是为了限制编写编译器的成本和难度。

    【讨论】:

      【解决方案2】:

      编译器看到while(false),这永远不会是真的,所以你无法到达println。这会引发错误。

      同时,虽然while(b) 也永远不会为真,但编译器不会自动知道这一点,因为b 不会自动为假,它是一个boolean,恰好有值false,它可能会在某个时候改变。 (这里没有,但它可能有)。

      为了使这一点更笼统,编译器将查看变量的类型,而不是变量实际上是什么。许多初级编程课程都有部分处理多态性和类型转换在某些情况下如何导致运行时错误,以及在其他情况下如何导致编译器错误。如果你碰巧上过这样的课程,你可以认为你的问题在这里有类似的解释。

      【讨论】:

        【解决方案3】:

        这对我来说很有意义。 While (false) 永远不会成功计算,而在 while(b) 的情况下 - b 的值可以在程序生命周期的某个时刻更新为 true。

        【讨论】:

          【解决方案4】:

          编译器不是很聪明。它会找到一个可以证明是错误条件的块,然后它会哭。给它这样的东西,javac 连线都看不到 远。对人类来说显而易见的东西对计算机来说不一定是显而易见的,反之亦然。

          【讨论】:

            【解决方案5】:

            编译器看到while(false) 并且可以确定其中的块虽然永远不会执行。

            如果是布尔值,b 的值是在运行时评估的,所以它不会阻止你

            【讨论】:

              猜你喜欢
              • 2022-01-21
              • 2022-01-17
              • 2013-03-12
              • 2018-02-26
              • 2012-05-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多