问题
Java's compiler, at least the one from Oracle that I use, refuses to recognize System.exit() as a procedure termination. For example, the following code gives a compilation error:
public static int readInteger( ArrayList<String> listLines, int iLineNumber0 ){
try {
int value = Integer.parseInt( listLines.get( 0 ) );
return value;
} catch( Throwable t ) {
System.err.println( "error reading line: " + iLineNumber0 + ": " + t );
System.exit( -1 );
}
}
The error is: "Missing return statement." Therefore, to make this work I have to add in a return statement like this (compiles successfully):
public static int readInteger( ArrayList<String> listLines, int iLineNumber0 ){
try {
int value = Integer.parseInt( listLines.get( 0 ) );
return value;
} catch( Throwable t ) {
System.err.println( "error reading line: " + iLineNumber0 + ": " + t );
System.exit( -1 );
}
return 0; // unreachable code
}
Ironically, the final return statement that is needed is unreachable code, although the compiler does not realize this either.
回答1:
Java's compiler, at least the one from Oracle that I use, refuses to recognize System.exit() as a procedure termination.
Yes, it would. As far as the compiler is concerned, it's just a void
method. There's no way of indicating "this method never returns normally" in a method signature, and no such concept in the language. For example:
public void alwaysThrow()
{
throw new RuntimeException();
}
...
alwaysThrow();
System.out.println("This line is never reached");
The last line in the above snippet is still reachable as far as the compiler is concerned, even though we know it will never execute. Likewise your extra return statement is technically reachable, but practically unreachable.
Basically this could be deemed a flaw in the language, although it's one which affects most languages as far as I'm aware. While it would be nice to be able to represent methods like this, it's rarely a real issue in real life.
If you find yourself bothered by it, you could write a helper method:
public RuntimeException systemExit(int exitValue)
{
System.exit(exitValue);
return new RuntimeException("Shouldn't get here");
}
Then call it as:
throw systemExit();
That will ensure that the end of the statement is unreachable as far as the compiler is concerned, so you could have:
catch (Throwable t) {
System.err.println("error reading line: " + iLineNumber0 + ": " + t);
throw systemExit(-1);
}
... and your compiler error would go away.
Note that there are other similar situations where reachability isn't everything we might want. For example:
int foo() {
int x = someValue();
if (x > 10) {
return 1;
}
if (x <= 10) {
return 20;
}
// Is this reachable or not?
}
We know that any value of x
will either be greater than 10 or less-than-or-equal-to 10, so the final line is practically unreachable but the rules of the language don't express that... so even a smart compiler can't actually treat the above code as valid without violating the language specification.
回答2:
Consider this: you've loaded a different runtime library whose System.exit
does not exit. Now what will happen at the end of the method? The compiler would rather have a concrete answer about this, so it doesn't make any special assumptions about System.exit
(or Runtime.exit
).
If it did, this would only add complications to the language specification for no real benefit. Exit calls are not common, and indeed, your code is not a good example of using one, because even if it did not require the unreached return statement, it still hides the original exception that caused the problem. I would replace the println/exit calls with:
throw new RuntimeException("Error reading line " + iLineNumber0, t);
When an exit call is really needed in a non-void method, it is easy to add a throw null;
or throw new Error();
or return ...;
below it.
Ironically, the final return statement that is needed is unreachable code, although the compiler does not realize this either.
This feature can't be added as it would break existing code.
回答3:
You could return your value outside the try-catch block:
public static int readInteger( ArrayList<String> listLines, int iLineNumber0 ){
int value = 0;
try {
value = Integer.parseInt( listLines.get( 0 ) );
} catch( Throwable t ) {
System.err.println( "error reading line: " + iLineNumber0 + ": " + t );
System.exit( -1 );
}
return value;
}
回答4:
error is not because of System.exit()
code but method expects return value in catch but syetm.exit
return type is void.
complete scenario explanation.
Any method if it expects return
value, then method should return a value under all possible circumstances and that too only one return
should come in all situations.
But in your first case
you have put return
only on try but not on catch, so it is complaining as expected return statement. because there is no return when exception occurs and its caught under that catch block.
in your second case,
you have put return
at try and outside try/catch. then return becomes unreachable code because try is already having return, so it should not have more than one return because after try one more return which is illegal in java.
so solution
put return in try and catch both but not outside try/catch.
or
put return directly outside try and catch.
solution 1 program
public static int readInteger( ArrayList<String> listLines, int iLineNumber0 ){
int value = 0;
try {
value = Integer.parseInt( listLines.get( 0 ) );
return value;
} catch( Throwable t ) {
System.err.println( "error reading line: " + iLineNumber0 + ": " + t );
System.exit( -1 );
return value;
}
}
solution 2 program
public static int readInteger( ArrayList<String> listLines, int iLineNumber0 ){
int value = 0;
try {
value = Integer.parseInt( listLines.get( 0 ) );
//return value;
} catch( Throwable t ) {
System.err.println( "error reading line: " + iLineNumber0 + ": " + t );
System.exit( -1 );
// return value;
}
return value;
}
let me know for any doubts.
来源:https://stackoverflow.com/questions/23446477/why-does-java-compiler-refuse-to-recognize-system-exit-as-a-procedure-terminat