88bf必发唯一娱乐官网 14

88bf必发唯一娱乐官网try、catch、finally详解,你不知道的异常处理

介绍

不管是新手还是工作几年的老油条,对try{}catch{}来说是不陌生的。他可以来帮助我们获取异常信息,在try中的代码出现错误,火灾catch代码块中被捕获到。官方也给了详细的解释:。

抛出异常时,公共语言运行库(CLR)会查找catch处理此异常的语句。如果当前正在执行的方法不包含这样的catch块,则CLR会查看调用当前方法的方法,依此类推调用堆栈。如果未catch找到任何块,则CLR向用户显示未处理的异常消息并停止执行该程序。

以上的这些基础我们可能都了解。但是你真的了解他的运行步骤吗?我就是带着这个疑问进行了一下的几个测试。

1.java异常架构图

简单示例:

既然有了疑问就带着疑问想办法验证吧,下面我们通过多个例子来一步一步的分析得到我们想要的结果。

88bf必发唯一娱乐官网 1

简单的try catch

首先是一个try中没有异常的示例:

 static void Main(string[] args)
        {
            string result =GetStr();
            Console.WriteLine(result);
            Console.ReadLine();
        }
        public static string GetStr()
        {
            try
            {
                Console.WriteLine("走到:try");
                return "这里是try返回值";
            }
            catch (Exception e)
            {
                Console.WriteLine("走到:catch");
                return "这里是catch返回值";
            }
            finally
            {
                Console.WriteLine("走到:finally");
            }
            return "这里是方法底部返回值";
        }

运行结果:

88bf必发唯一娱乐官网 2

执行分析:

这是最简单最常见的示例,没有发生异常,然后没有走catch,执行顺序是try=>finally=>return;

所有我们得到一个还不确定的结果在GetStr方法中不会执行方法自己的return;

但是finally方法块都会执行;

粉红色的是受检查的异常(checked exceptions),其必须被
try{}catch语句块所捕获,或者在方法签名里通过throws子句声明.受检查的异常必须在编译时被捕捉处理,命名为
CHecked Exception
是因为Java编译器要进行检查,Java虚拟机也要进行检查,以确保这个规则得到遵守.
绿色的异常是运行时异常(runtime
exceptions),需要程序员自己分析代码决定是否捕获和处理,比如
空指针,被0除…
而声明为Error的,则属于严重错误,需要根据业务信息进行特殊处理,Error不需要捕捉。

来个异常的:

下面我们让try方法块出错就好了,然后我们修改一下代码如下:

 public static string GetStr()
        {
            try
            {
                int value = 0;
                Console.WriteLine("走到:try");
                var i = 1 / value;//这里会出错 0不能被整除
                return "这里是try返回值";
            }
            catch (Exception e)
            {
                Console.WriteLine("走到:catch");
                return "这里是catch返回值";
            }
            finally
            {
                Console.WriteLine("走到:finally");
            }
            return "这里是方法底部返回值";
        }

运行结果:

88bf必发唯一娱乐官网 3

执行分析:

这里在try发生了异常,然后没有正常返回,进入到了catch方法块:try=>catch=>finally=>return;

这里我们可以确定:

  • 不管try有没有出错finally方法块都会被执行。【快记笔记,知识点。】
  • 就算try和catch方法都有return,finally都会执行;
  • 只要try或者catch return返回,try catch 之外的return都无效;

说到这里有些不懂得人可能会有疑问?那在finally写个return是什么结果哪?很不幸的告诉你,不能这么写,写了会怎么样,哼会提示:控制不能离开finally子句主体;

2.try{}里有一个return语句,那么紧跟在这个try后的finally
{}里的code会不会被执行,什么时候被执行,在return前还是后?

验证return的值

上面我们知道了怎样都会执行finally,但是执行了finally对我们的正返回值有没有印象哪,例如我在try里面对一个变量赋值为a字符串,进行了返回,但是在finally里面修改成了b字符串。会不会被修改哪?

我们还是老代码,然后修改成我们想的样子:

public static string GetStr()
        {
            string str = "";
            try
            {
                str = "修改成了a";
                Console.WriteLine("走到:try");
                // return "这里是try返回值";
                return str;
            }
            catch (Exception e)
            {
                Console.WriteLine("走到:catch");
                return "这里是catch返回值";
            }
            finally
            {
                str = "修改成了b";
                Console.WriteLine("走到:finally");
            }
            return "这里是方法底部返回值";
        }

运行结果:

88bf必发唯一娱乐官网 4

执行分析:

没有异常还是老样子:执行顺序是try=>finally=>return;

但是我们在finally修改了str字符串,但是通过输出结果我们得到的还是a字符串,

所有我们得到结论:虽然finally方法会被执行但是,返回结果不会被改变,也就是如果finally是在return之后执行的那么他会把返回结果先保存起来,然后不管finally代码执行了什么,都不会影响到返回结果,等finally执行完成在返回结果。

也许你的答案是在return之前,但往更细地说,我的答案是在return中间执行,请看下面程序代码的运行结果:

 多个重复try

那么我们可以写多个try{}try{}这样的语句吗?不行,会直接报错,其实这样写没有任何意义。

 1 public  classTest {  
 2   
 3     public static void main(String[] args) {  
 4        System.out.println(newTest().test());  
 5     }  
 6     staticint test()  
 7     {  
 8        int x = 1;  
 9        try  
10        {  
11            return x;  
12        }  
13        finally  
14        {  
15            ++x;  
16        }  
17     }  
18 }  

多个重复catch

那么重复多个catch哪?这个是可以的例如下面我这样:

  try
            {
                str = "修改成了a";
                Console.WriteLine("走到:try");
                // return "这里是try返回值";
                return str;
            }
            catch(InvalidCastException e) {
            }
            catch (Exception e)
            {
                Console.WriteLine("走到:catch");
                return "这里是catch返回值";
            }

这个是被允许的,因为这是有意义的写法。

———执行结果 ———

开始升级

为什么要一定写try-catch-finally 我只写其中一部分不可以吗?

运行结果是1,为什么呢?主函数调用子函数并得到结果的过程,好比主函数准备一个空罐子,当子函数要返回结果时,先把结果放在罐子里,然后再将程序逻辑返回到主函数。所谓返回,就是子函数说,我不运行了,你主函数继续运行吧,这没什么结果可言,结果是在说这话之前放进罐子里的。

 try-catch

那么我们这次不写finally试一试吧。try方法块没有异常已经不用测了,因为上面我们已经确认过了。会返回try的内容。那么就try异常吧。

 public static string GetStr()
        {
            try
            {
                Console.WriteLine("走到:try");
                int value = 0;
                int s = 1 / value;              
                return "这里是try返回值";
            }
            catch (Exception e)
            {
                Console.WriteLine("走到:catch");
                return "这里是catch返回值";
            }
            return "这里是方法底部返回值";
        }

运行结果:

88bf必发唯一娱乐官网 5

执行分析:

通过可以正常运行我们知道这样写一点问题都没有,所以结果就是

  • finally也不是必须的。
  • 如果catch没有return 就会返回底部return方法。这是我们的常识。

这样做有什么作用或者意义哪,通常我们可以上面说的定义多个catch来检测异常,还有一个用途就是忽略异常,就是这种异常你系统可以被运行,就可以catch内不写return正常跳过异常执行下面的方法体。但是不是很被建议,

3。final, finally, finalize的区别。

try-finally

那么try-finally哪,这样写也是被允许的。

这样单独写第一就是在finally语句块内做try的资源释放。正常情况下try没有异常,在finally中处理try语句块的资源释放。

第二就是try发生了异常,其实finally起到的作用还是一样的。但是这里区别在于如果异常未经处理,可能就导致程序退出了。所有执不执行已经无所谓了。我们来个异常示例:

88bf必发唯一娱乐官网 688bf必发唯一娱乐官网 7

static void Main(string[] args)
        {
            string result = "";
            try
            {
                result = GetStr();
            }
            catch (Exception e)
            {
                Console.WriteLine("主方法catch:");
            }
            Console.WriteLine(result);
            Console.ReadLine();
        }
        public static string GetStr()
        {
            try
            {
                Console.WriteLine("走到:try");
                int value = 0;
                int s = 1 / value;               
                return "这里是try返回值";
            }

            finally
            {
                Console.WriteLine("走到:finally");
            }

            return "这里是方法底部返回值";
        }

View Code

运行结果:

88bf必发唯一娱乐官网 8

执行分析:

try发生了异常,但是因为finally始终都会执行所有也会执行,然后异常被调用方法内的catch捕获执行顺序:try=>finally=>catch(主方法)

所有我们得到结果:

  • try-finally可以运行
  • try如果没有catch但是发生异常会向上找catch方法块来捕获。知道没有系统崩溃。

以上的例子都是非控制(系统出现异常就自动抛出了)的抛出异常,那么我们可以控制异常的抛出点吗?当然可以。

  final
用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。

throw

还是老习惯先上官方解释,发出程序执行期间出现异常的信号。

到底什么意思哪,我个人理解就是一个告诉你是不是出现异常的标志,就像信号灯一样,亮了什么颜色就代表着什么意思
,当然就是打个比方。信号灯一定是对的,但是这个可不是啊。
简单来总结他就两个功能:第一是告诉别人有异常,第二就是重新发出异常。

内部类要访问局部变量,局部变量必须定义成final类型,例如,一段代码……

告诉别人有异常

简单来说就是自己可以定义一个异常,然后给上层代码处理。(我就是在这想告诉你有异常)

88bf必发唯一娱乐官网 988bf必发唯一娱乐官网 10

static void Main(string[] args)
        {
            string result = "";
            try
            {
                Console.WriteLine("主方法try:");
                result = GetStr(6);
            }
            catch (IndexOutOfRangeException e)
            {
                Console.WriteLine($"主方法catch抛出异常:{e.GetType().Name}");
            }
            Console.WriteLine("主方法结束");
            Console.ReadLine();
        }
        public static string GetStr(int index)
        {
            if (index < 0 || index > 5)
            {
                Console.WriteLine("进入异常:");
                throw new IndexOutOfRangeException();
            }
            return "正确返回";
        }

View Code

运行结果:

88bf必发唯一娱乐官网 11

执行分析:

在主方法里调用GetStr方法,然后传入了6判断进入if然后给自己给出了异常,退出当前程序进入主方法捕获异常catch中,捕获到异常打印。这里就展示了自己在某种情况下定义一个异常然后给上层抛出。

 

重新引发异常

这个与上面有什么不同哪,功能都是一样的,但是效果却不一样,这个是我发生了异常但是我不处理,我在继续告诉别人让别人处理。下面我们只需要把上面的GetStr方法修改成这样:

88bf必发唯一娱乐官网 1288bf必发唯一娱乐官网 13

 public static string GetStr(int index)
        {
            try
            {
                if (index < 0 || index > 5)
                {
                    Console.WriteLine("进入异常:");
                    throw new IndexOutOfRangeException();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine($"进入异常catch重新抛出异常:{e.GetType().Name}");
                throw;
            }
            return "正确返回";
        }

View Code

运行结果:

88bf必发唯一娱乐官网 14

执行分析:

在主方法里调用GetStr方法,然后传入了6判断进入if然后给自己给出了异常,在GetStr方法内的catch捕获到异常,但是他没有处理,有重新使用Throw来引发异常,把异常传到了上层(主方法),最后还是主方法的catch来处理异常。

 

finally是异常处理语句结构的一部分,表示总是执行。

 

finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用

4.请写出你最常见到的5个runtime exception。

这道题主要考你的代码量到底多大,如果你长期写代码的,应该经常都看到过一些系统方面的异常,你不一定真要回答出5个具体的系统异常,但你要能够说出什么是系统异常,以及几个系统异常就可以了,当然,这些异常完全用其英文名称来写是最好的,如果实在写不出,那就用中文吧,有总比没有强!

所谓系统异常,就是…..,它们都是RuntimeException的子类,在jdk
doc中查RuntimeException类,就可以看到其所有的子类列表,也就是看到了所有的系统异常。我比较有印象的系统异常有:NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException。

5.JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?

Java
通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在
Java 中,每个异常都是一个对象,它是 Throwable
类或其它子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java
的异常处理是通过 5 个关键词来实现的:try、catch、throw、throws 和
finally。一

般情况下是用 try
来执行一段程序,如果出现异常,系统会抛出(throws)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理;

 try 用来指定一块预防所有“异常”的程序;

 catch 子句紧跟在 try 块后面,用来指定你想要捕捉的“异常”的类型;

 throw 语句用来明确地抛出一个“异常”;

 throws 用来标明一个成员函数可能抛出的各种“异常”;

 Finally 为确保一段代码不管发生什么“异常”都被执行一段代码;

 可以在一个成员函数调用的外面写一个 try 语句,   
在这个成员函数内部写另一个 try 语句保护其他代码。每当遇到一个 try
语句,“异常”的框架就放到堆栈上面,直到所有的 try 语句都完成。如果下一级的
try 语句没有对某种“异常”进行处理,堆栈就会展开,直到遇到有处理这种“异常”的
try 语句。

6.运行时异常与一般异常有何异同?

异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。

7..下面的程序代码输出的结果是多少?

public class  smallT{

         public static void  main(String args[]){

                   smallT t  = new smallT();

                   int  b =  t.get();

                   System.out.println(b);

         }

         public int  get()

         {

                   try     {return 1;}

                   finally{return 2;}

         }}

返回的结果是2。

我可以通过下面一个例子程序来帮助我解释这个答案,从下面例子的运行结果中可以发现,try中的return语句调用的函数先于finally中调用的函数执行,也就是说return语句先执行,finally语句后执行,所以,返回的结果是2。Return并不是让函数马上返回,而是return语句执行后,将把返回结果放置进函数栈中,此时函数并不是马上返回,它要执行finally语句后才真正开始返回。

在讲解答案时可以用下面的程序来帮助分析:

public  class Test {

    public static void main(String[]args) {

        System.out.println(new Test().test());;

    }

    int test()

    {

        try         {return func1();}

        finally    {return func2();}

    }

   

    int func1()

    {

        System.out.println(“func1”);

        return 1;

    }

    int func2()

    {

        System.out.println(“func2”);

        return 2;

    }  

}

———–执行结果—————–

func1

func2

2

结论:finally中的代码比return 和break语句后执行