while(true); loop throws Unreachable code when isn't in a void

后端 未结 4 814
时光说笑
时光说笑 2020-12-29 20:28

I was doing some small programs in java. I know that if I write while(true); the program will freeze in this loop. If the code is like that:

4条回答
  •  -上瘾入骨i
    2020-12-29 21:08

    Unreachable code is a compile time error that simply says 'the flow of this program doesn't make sense; something will never ever be reached'.

    Obviously your tests perform how they do due to an endless loop, but why does the first fail with a compile time error?

    A while statement can complete normally if at least one of the following is true:

    • The while statement is reachable and the condition expression is not a constant expression (§15.28) with value true.

    • There is a reachable break statement that exits the while statement.

    Alright, but what about methods invocations (such as a()) - why do tests 2 and 3 successfully compile?

    • An expression statement can complete normally if it is reachable.

    Since a method invocation is considered an expression, they will always be reachable so long as nothing before it blocks its path of logical execution.


    To better illustrate some reasoning behind this compilation mechanism, let's take an if statement, for example.

    if(false)
       System.out.println("Hello!"); // Never executes
    

    The above will be correct at compile time (though many IDE's will definitely whine!).

    The Java 1.7 Specification talks about this:

    The rationale for this differing treatment is to allow programmers to define "flag variables" such as:

    static final boolean DEBUG = false;
    

    and then write code such as:

    if (DEBUG) { x=3; }
    

    The idea is that it should be possible to change the value of DEBUG from false to true or from true to false and then compile the code correctly with no other changes to the program text.

    Further, there is actually a backwards compatibility reason as well:

    This ability to "conditionally compile" has a significant impact on, and relationship to, binary compatibility (§13). If a set of classes that use such a "flag" variable are compiled and conditional code is omitted, it does not suffice later to distribute just a new version of the class or interface that contains the definition of the flag. A change to the value of a flag is, therefore, not binary compatible with pre-existing binaries (§13.4.9). (There are other reasons for such incompatibility as well, such as the use of constants in case labels in switch statements; see §13.4.9.)


    Most (per the spec), if not all, implementations of the Java compiler do not traverse into methods. When parsing your Java code itself, it sees a() as just a MethodInvocationElement, meaning 'This code calls other code. I really don't care, I'm just looking at syntax.'. Syntactically, it makes sense for subsequent code to belong after a call to a().

    Keep in mind performance costs. Compilation already takes a considerable amount of time. In order to keep things quick, the Java compiler doesn't actually recurse into methods; that would take ages (the compiler would have to evaluate many, many paths of code -- in theory).


    To further reiterate that it's syntactically driven is to add a return; statement directly after your loop in a(). Doesn't compile, does it? Syntactically, though, it makes sense without it.

提交回复
热议问题