Consider this function :
public boolean foo(){ System.exit(1); //The lines beyond this will not be read int bar = 1; //L1 //But the return statement is required for syntactically correct code return false; //L2 //error here for unreachable code //int unreachable = 3; //L3 }
Can someone please explain why L1 and L2 visibly not reachable does not give warnings but L3 does.
exit(0) : Indicates successful termination. exit(1) or exit(-1) or any non-zero value – indicates unsuccessful termination.
As mentioned earlier, System. exit(0) method terminates JVM which results in termination of the currently running program too. Status is the single parameter that the method takes. If the status is 0, it indicates the termination is successful.
return statement is used inside a method to come out of it. System. exit(0) is used in any method to come out of program. System.
exit(0) : Generally used to indicate successful termination. exit(1) or exit(-1) or any other non-zero value – Generally indicates unsuccessful termination. Note : This method does not return any value. The following example shows the usage of java.
The Java compiler doesn't know anything about System.exit
. It's just a method as far as it's concerned - so the end of the statement is reachable.
You say that L1
and L2
are "visibly not reachable" but that's only because you know what System.exit
does. The language doesn't - whereas it does know what a return
statement does, so it knows that L3
really isn't reachable.
I sometimes think it would be useful to be able to declare that a method isn't just void
, but never terminates normally - it never just returns (although it may throw an exception). The compiler would then be able to use that information to make the end of any calling expression unreachable, preventing this sort of thing from being a problem. However, that's just my dreams around language design - Java doesn't have anything similar, and it would be a very bad idea for the compiler to "know" that particular JRE methods will never return normally, when that concept can't be expressed directly within the language.
Instead, the compiler is bound by the rules of section 14.21 of the JLS, including:
- The first statement in a non-empty block that is not a switch block is reachable iff the block is reachable.
- Every other statement S in a non-empty block that is not a switch block is reachable iff the statement preceding S can complete normally.
...
An expression statement can complete normally iff it is reachable.
(A method call is an expression statement.)
Then from section 8.4.7:
If a method is declared to have a return type, then a compile-time error occurs if the body of the method can complete normally (§14.1).
and in 14.1:
Unless otherwise specified, a statement completes normally if all expressions it evaluates and all substatements it executes complete normally.
So the call to System.exit()
can complete normally as far as the compiler is concerned, which means the body of the foo
method can complete normally, which leads to the error.
Because as far as the compiler is concerned, System.exit()
is just another method call.
The fact that what it does is end the process can only be found out from the implementation (which is native code, not that it makes any difference).
If you have to put System.exit()
in your code (usually it's best to avoid it, unless you want to return a code other than 0), it should really be in a method that returns void
, main()
for example. It's nicer that way.
As for the reachability, the explanation is the same: return
is a keyword of the Java language, so the compiler or the parser the IDE uses can tell that it's theoretically impossible for code after the return
statement to be executed. These rules are defined here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With