Ela's Notes
So Be It


Hitokoto ·
try-catch-finally的作用
Elatis   Java   594 | 文章字数: 5541 字

搬运自旧站,为了不让博客dead那么快就搬了一篇过来
本篇运用Java讲解了一下try-catch-finally语句的作用
适用于其它支持trycatch的语言,如php

语句的基本形式:

try{
//代码
}catch(Exception e){
//异常处理
}

这可以保证你的程序出现异常状态后可以继续运行下去.例如出现了除数为0的情况,如果没有这个语句,程序就会直接崩溃,而使用了这个语句,不仅程序可以运行下去,还可以知道程序的异常之处.
测试如下代码:

public class text {

    public static void main(String[] args)
    {

        try {
            int a;
            a=1/0;
            System.out.println(a);
        }catch(Exception e){
            System.out.println("报错");
        }
        System.out.println("I AM ALIVE!");
    }
}

运行该代码后,会输出

报错
I AM ALIVE!

可见程序在运行过程中虽然出现了"1/0"这种会使程序崩溃的情况,但是程序并没有崩溃,而是继续运行下去了.

那么如何知晓程序究竟为什么会崩溃呢?其实在刚才的代码里,"catch(Exception e)"这句的意思就是把错误信息储存在e里了.所以我们只需要输出e即可.
运行如下代码:

public class text {

    public static void main(String[] args)
    {

        try {
            int a;
            a=1/0;
            System.out.println(a);
        }catch(Exception e){
            System.out.println("报错");
            System.out.println(e);
        }
        System.out.println("I AM ALIVE!");
    }
}

输出结果:

报错
java.lang.ArithmeticException: / by zero
I AM ALIVE!

说明报错原因是除数为0.
当然我们还能知晓更多信息,将刚才代码中的"System.out.println(e);"这一句改为"e.printStackTrace();",再运行程序,输出如下:

报错
java.lang.ArithmeticException: / by zero
    at text.main(text.java:9)
I AM ALIVE!

通过输出的第三行我们可以知晓是在代码的第九行出现了错误.
知晓错误信息后,如果我们不想改动try{}里的代码,而是想让它在出错后运行另一种方法该怎么办呢?只需要在catch(Exception e){}里加入你想要的方法就行了.

还有另一个语句"finally{}",通常放在catch{}之后,作用为无论有没有报错,都最终运行finally{}里面的方法.也许有人会说为什么不把方法直接放在catch{}之后而要加个finally{},接下来将会说明.
首先我们来测试一下finally对于整个函数的作用
运行如下代码:

public class text {
    public void mtry(){ //这是一个自定义方法
        String a,b;
        try {
            a="try";
            b="Ttry";
        }catch(Exception e){
            a="catch";
            b="Ccatch";
        }finally {
            a="finally";
            b="Ffinally";
        }
        System.out.println(a);
        System.out.println(b);
    }
    public static void main(String[] args){
        text te=new text();//这步是让text类调用自己
        te.mtry();//使用text类的mtry方法
    }
}

运行这个代码后,会输出:

finally
Ffinally

说明即使try{}语句内没有报错,程序还是运行了finally{},使ab重新赋值.

接下来我们让try{}强行报错:
在try{}的花括号里添加

int x=1/0;

无疑这样会让try报错,运行后会输出:

finally
Ffinally

说明即使在try报错,运行了catch语句后,finally语句还是最终运行了.

虽然finally语句无论如何都会运行,但我们可以使用一些其它方法来控制它,以达到我们的目的.
在try的花括号里的最后加入

return a;

再对程序进行一些改动,变成如下这样

public class text {
    public String mtry(){
        String a,b;
        try {
            a="try";
            b="Ttry";
            return a;
        }catch(Exception e){
            a="catch";
            b="Ccatch";
        }finally {
            a="finally";
            b="Ffinally";
            System.out.println("Finally!");
        }
        System.out.println(a);
        System.out.println(b);
        return a;
    }
    public static void main(String[] args){
        String a;
        text te=new text();
        a=te.mtry();
        System.out.println("returned: "+a);
    }
}

大家先猜猜运行后会输出什么,再往下看.

你猜的是不是

returned: try

如果是,恭喜你,你错了.
真正运行后会输出:

Finally!
returned: try

按一般我们对函数的理解,在try语句中a,b赋值完毕,而且没有报错,应该会直接return a.但是finally是特殊的.它的运行时间为try{}catch{}被关闭时,即运行完成后,但它会在return执行前执行,执行完后才会return.

我们可以再对程序进行一些改动来理解.再finally的大括号中的最后再加入

return a;

如果你的代码没有写错,那么上面那个程序的这段:

    System.out.println(a);
    System.out.println(b);
    return a;

应该会报错:"unreachable code",意思就是无论如何,这段代码永远不可能被执行.我们姑且先将其注释掉.
改动完成后,代码应当是这样的:

public class text {
    public String mtry(){
        String a;
        try {
            a="try";
            return a;
        }catch(Exception e){
            a="catch";
        }finally {
            a="finally";
            System.out.println("Finally!");
            return a;
        }
        /*System.out.println(a);
        return a;*/
    }
    public static void main(String[] args){
        String a;
        text te=new text();
        a=te.mtry();
        System.out.println("returned: "+a);
    }
}

然后我们再运行,你应该猜到会输出什么了,输出结果如下:

Finally!
returned: finally

而我们都清楚,try{}确实被运行且没报错,但是函数却return了finally,说明finally的return的执行还要在try的return执行之前.
要是你还不信try{}已经被运行了,可以在里面再加一个输出来鉴定.

若try报错,运行了catch语句,其实也和上面的道理类似,现在令try强行报错,并且在catch里加入return a,然后我们再试试

public class text {
    public String mtry(){
        String a;
        try {
            a="try";
            int x=1/0;
            return a;
        }catch(Exception e){
            a="catch";
            return a;
        }finally {
            a="finally";
            System.out.println("Finally!");
            return a;
        }
        /*System.out.println(a);
        return a;*/
    }
    public static void main(String[] args){
        String a;
        text te=new text();
        a=te.mtry();
        System.out.println("returned: "+a);
    }
}

运行结果如下:

Finally!
returned: finally

综上所诉,我们可以通过将try{}catch{}finally{}写在自定义方法里并用return来更好的控制整个语句的运行.
然而还有一点疑惑的地方:既然在finally{}内将a赋值了,为何还return了在try语句里赋值的a?
我们不妨在finally里面输出a,同时将finally里的return删掉/注释掉.

运行如下代码:

public class text {
    public String mtry(){
        String a;
        try {
            a="try";
            return a;
        }catch(Exception e){
            a="catch";
            return a;
        }finally {
            a="finally";
            System.out.println(a);
        }
    }
    public static void main(String[] args){
        String a;
        text te=new text();
        a=te.mtry();
        System.out.println("returned: "+a);
    }
}

输出:

finally
returned: try

为何两个a会不同?其实我也很疑惑这一点,经过百度,大概是这样的:
在try运行到return a这一步时,同时运行了finally,但此时try中要return什么其实已经确定了,程序已经自动将要return的值转存到另一个地方了,所以finally对a进行改动,并不影响整个函数的返回值,除非直接在finally中return另一个东西.

而刚才还遗留的两个问题也可以解决了:
1) 为何不将finally{}内的代码直接写在catch{}后面: 因为有时候我们需要单独操作某个变量,而不改动其它变量,就需要finally出场了.
2) 为何刚才会出现"unreachable code"的报错字样: 因为finally无论如何都会运行,所以在finally里的return必定会运行,自然不可能运行到下一个语句.由此我们可以知道,尽量不要在finally中添加return,否则可能导致一些莫名其妙的错误.

参考资料:
https://www.cnblogs.com/aigongsi/archive/2012/04/19/2457735.html
https://www.cnblogs.com/hyzxx/p/5151911.html

评论

  1. ~魔法使之家~

    我的话,就一般是
    main(){
    try{
    程序全部qwq
    }catch{
    忽略全部错误辣
    }

    }

发送失败 可能是您的发言太频繁或联系方式有误

提交评论

Theme LightWhite Made by Archeb With
自豪地使用Typecho
© 2017 - 2019 Ela's Notes 全站共 19.96 W 字
博客已经运行了