为什么Java编译器拒绝将System.exit()识别为过程终止?
Java的编译器,至少是我使用的Oracle编译器,拒绝将System.exit()识别为过程终止。例如,以下代码给出了一个编译错误:为什么Java编译器拒绝将System.exit()识别为过程终止?,java,compiler-errors,Java,Compiler Errors,Java的编译器,至少是我使用的Oracle编译器,拒绝将System.exit()识别为过程终止。例如,以下代码给出了一个编译错误: public static int readInteger( ArrayList<String> listLines, int iLineNumber0 ){ try { int value = Integer.parseInt( listLines.get( 0 ) ); return value;
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 );
}
}
publicstatic int readInteger(ArrayList listLines,int-ilineumber0){
试一试{
int value=Integer.parseInt(listLines.get(0));
返回值;
}捕获(可丢弃的t){
System.err.println(“错误读取行:+ilineumber0+”:“+t”);
系统退出(-1);
}
}
错误是:“缺少return语句”。因此,要使这项工作正常,我必须添加一个如下的return语句(编译成功):
publicstatic int readInteger(ArrayList listLines,int-ilineumber0){
试一试{
int value=Integer.parseInt(listLines.get(0));
返回值;
}捕获(可丢弃的t){
System.err.println(“错误读取行:+ilineumber0+”:“+t”);
系统退出(-1);
}
返回0;//无法访问的代码
}
具有讽刺意味的是,所需的最终返回语句是无法访问的代码,尽管编译器也没有意识到这一点
Java的编译器,至少是我使用的Oracle编译器,拒绝将System.exit()识别为过程终止
是的,会的。就编译器而言,它只是一个void
方法。在方法签名中无法表示“此方法永远不会正常返回”,在语言中也没有这样的概念。例如:
public void alwaysThrow()
{
throw new RuntimeException();
}
...
alwaysThrow();
System.out.println("This line is never reached");
int foo() {
int x = someValue();
if (x > 10) {
return 1;
}
if (x <= 10) {
return 20;
}
// Is this reachable or not?
}
就编译器而言,上面代码段的最后一行仍然可以访问,尽管我们知道它永远不会执行。同样,您的额外返回语句在技术上是可以访问的,但实际上是无法访问的
基本上,这可以被认为是语言中的一个缺陷,尽管据我所知,它影响了大多数语言。虽然能够像这样表示方法会很好,但它在现实生活中很少是一个真正的问题
如果您发现自己被它困扰,您可以编写一个helper方法:
public RuntimeException systemExit(int exitValue)
{
System.exit(exitValue);
return new RuntimeException("Shouldn't get here");
}
然后称之为:
throw systemExit();
这将确保编译器无法访问语句结尾,因此您可以:
catch (Throwable t) {
System.err.println("error reading line: " + iLineNumber0 + ": " + t);
throw systemExit(-1);
}
。。。你的编译器错误就会消失
注意,在其他类似的情况下,可达性并不是我们想要的一切。例如:
public void alwaysThrow()
{
throw new RuntimeException();
}
...
alwaysThrow();
System.out.println("This line is never reached");
int foo() {
int x = someValue();
if (x > 10) {
return 1;
}
if (x <= 10) {
return 20;
}
// Is this reachable or not?
}
intfoo(){
int x=someValue();
如果(x>10){
返回1;
}
如果(x错误不是因为System.exit()
code,但方法期望catch中有返回值,但syetm.exit
返回类型无效
完整的场景解释
任何方法如果期望return
value,那么该方法在所有可能的情况下都应该返回一个值,并且在所有情况下也只能返回一个return
但在你的第一个案例中
您已将return
仅放在try上,而不放在catch上,因此它将作为预期的return语句进行抱怨。因为在异常发生时并没有返回,并且在catch块下捕获了异常
在你的第二个案例中
您已将return
放在try和try/catch之外。然后return成为不可访问的代码,因为try已经有了return,所以它不应该有多个return,因为在try之后还有一个return,这在java中是非法的
所以解决方案
将return放在try-and-catch中,但不要放在try/catch之外
或
把回程直接放在外边,试着接住
解决方案1计划
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;
}
}
publicstatic int readInteger(ArrayList listLines,int-ilineumber0){
int值=0;
试一试{
value=Integer.parseInt(listLines.get(0));
返回值;
}捕获(可丢弃的t){
System.err.println(“错误读取行:+ilineumber0+”:“+t”);
系统退出(-1);
返回值;
}
}
解决方案2计划
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;
}
publicstatic int readInteger(ArrayList listLines,int-ilineumber0){
int值=0;
试一试{
value=Integer.parseInt(listLines.get(0));
//返回值;
}捕获(可丢弃的t){
System.err.println(“错误读取行:+ilineumber0+”:“+t”);
系统退出(-1);
//返回值;
}
返回值;
}
如果有任何疑问,请告诉我。您可以在try-catch块之外返回您的值:
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;
}
publicstatic int readInteger(ArrayList listLines,int-ilineumber0){
int值=0;
试一试{
value=Integer.parseInt(listLines.get(0));
}捕获(可丢弃的t){
System.err.println(“错误读取行:+ilineumber0+”:“+t”);
系统退出(-1);
}
返回值;
}
考虑一下:您加载了另一个运行时库,它的系统.exit
没有退出。现在在方法结束时会发生什么?编译器希望对此有一个具体的答案,因此它不会对系统.exit
(或运行时.exit
)做出任何特殊的假设
如果它这样做了,这只会给语言规范增加复杂性,而没有真正的好处。退出调用并不常见,事实上,您的代码不是使用退出调用的好例子,因为即使它不需要unached return语句,它仍然隐藏了导致问题的原始异常。我将替换println/Exit calls与:
throw new RuntimeException("Error reading line " + iLineNumber0, t);
在非void方法中确实需要退出调用时,可以很容易地在其下方添加throw null;
或throw new Error();
或return…;
具有讽刺意味的是,所需的最终返回语句是无法访问的代码,尽管编译器也没有意识到这一点
无法添加此功能,因为它会破坏现有代码。因为它不是--它只是一个方法调用,与任何其他调用都无法区分。您还可以返回val