Java中关于try...catch的return规则

发布时间 2023-11-11 15:29:04作者: qiuer0121

本部分针对有return 要求的异常捕获和处理,具体的,try...catch语句存在于方法体中。

方法体中的try...catchreturn 总共有四种可能的地方:

try,catch,finally,方法体末尾(try…catch外)。

共存规则

  • finally中的return 和方法return不能同时存在。(显而易见的第一法则!)
  • try中的returncatch中的return 都有的时候,finally中的return可有可无,但是不能有方法return(编译器提示:方法return 不可到达)
  • trycatch中只有一个有return时,finally 中的return和方法return必须有且只能有一个。(否则:缺少return

共存问题还是很好理的。只要保证每种情况都必须有return就行。

ps.IDEA比较牛逼会在一定程度上分析逻辑……比如如果try里头第一句就是throw的话,try里的return也是会报错的。

int i=1;
try {
    throw new Exception();
    return i;
}//这样会报错。
--- --- --- --- ---
int i=1;
try {
    if(i==1) throw new Exception();
    return i;
}//但是这样不会。

执行顺序

规则

  1. try里头抛出异常被捕获后,try中之后的语句是不会被执行的,而是直接跳转到相应的catch
  2. 无论如何finally中的语句都会在方法返回之前被执行。
  3. finally或者方法体末尾有return时,它会覆盖trycatch中的return
  4. return返回的是一个引用,(可以理解为一个物理地址?)所以当只有trycatch中有return时,如果返回的是不可变类型,那么finally中对对象的”修改“实际上是创建了一个新对象,返回的自然是原来的值;如果返回的是可变类型finally中的修改就会对返回值生效。

实例

  1. 懒得打了,跳过。

int i=1;
try{
    throw new Exception();
}catch(Exception e){
    return i;//返回值为1
}finally{
    i++;
    System.out.println(i);//输出为2
}

finally块的递增操作不会影响catch块中的返回值,因为catch块已经执行完毕并返回了值,finally块中的代码只是在方法返回之前执行的。

  1. public static int get0() {
        int i=1;
        try {
            throw new Exception();
        } catch (Exception e) {
            System.out.println("error");
            return i;
        } finally {
            i++;
            System.out.println("i in finally block:" + i);
            return i;//最终返回2
        }
    }
    

    finally中的return覆盖了之前的return

  2. public static String get1() {
        String i = "ok";
        try {
            throw new Exception();
        } catch (Exception e) {
            System.out.println("error");
            return i;//最终返回"ok"
        } finally {
            i += " finally";
            System.out.println("i in finally: " + i);//输出i in finally: ok finally
        }
    }
    
    public static StringBuilder get2() {
        StringBuilder i = new StringBuilder("ok");
        try {
            throw new Exception();
        } catch (Exception e) {
            System.out.println("error");
            return i;//返回ok finally
        } finally {
            i.append(" finally");
            System.out.println("i in finally: " + i);//输出i in finally: ok finally
        }
    }
    

    其中,String(包括get0()中的int)是不可变类型,而StringBuilder是可变类型,因此导致了返回结果的不同。

当然,自己写代码时有事没事不要往finally里面加return,会导致调试复杂化。