详述try-catch-fianlly

  • 异常的定义

在java中,我们程序除了正常运行外还有一种情况,那就是异常。

Java语言将程序运行过程中所发生的不正常严重错误称为异常,对异常的处理称为异常处理。

它会中断正在运行的程序,正因为如此异常处理是程序设计中一个非常重要的方面,也是程序设计的一大难点。

众所周知,0不能做分母,而这段代码中的“1/0”便犯了这个错误,我们看到执行后输出了123,但是错误代码行以后的不再输出,所以异常的结果是中断正在运行中的程序。 

  • 异常的结构

异常的分类图

throwable有两个直接子类,Error类和Exception类。

Error : 合理的应用程序在执行过程中发生的严重问题。当程序发生这种严重错误时,通常的做法是通知用户并中止程序的执行。

而这实际上是编译器的问题,所以我们不进行过多探究。

  •  Exception:异常可分为运行时异常(RuntimeException)检查时异常(CheckedException)两种:

①1.RuntimeException:运行时异常,即程序运行时抛出的异常。这种异常在写代码时不进行处理,Java源文件也能编译通过。 RuntimeException异常类及其下面的子类均为运行时异常。

public class Unusual {
    public static void main(String[] args) {
        System.out.println(123);
	System.out.println(1/0);       //运行时异常,程序在编译时并未报错
	System.out.println(456);
    }
}

 这段代码在java中我们编写时并不会报错,并且java源文件也能通过javac命令生成class文件,但一旦运行,便会报错。

由于这个特点,这种异常我们可以不显式处理。

②2.CheckedException:检查时异常,又称为非运行时异常,这样的异常必须在编程时进行处理,否则就会编译不通过。Exception异常类及其子类(除去RuntimeException异常类及其子类)都是检查时异常。

 

比如这段代码,创建对象时的类名并不存在,编译时就没有通过,程序报错,针对这种异常,我们必须做显式处理,使程序在编译时就能够通过。

  • 异常的处理

Java中对异常的处理有如下两种方式:

①通过trycatchfinally关键字捕获异常;

②通过throwthrows关键字抛出异常;

这篇博客我们注重讲捕获异常

  • 捕获异常的语法结构
public class Unusual {
	public static void main(String[] args) {
		
		try{                                
		    System.out.println(1/0);           //可能抛出异常的语句块
		}
                catch(ArithmeticException e){          //异常类型,这里是ArithmeticException
                    e.printStackTrace();               //当捕获到所预测异常时执行的语句块
		}
                finally{
	     	    System.out.println("程序执行完毕"); //无论是否发生异常都会执行的代码
                }
	}
}

因为1/0确实是数学类型的异常,所以程序执行的结果为

并且由于try catch finally语句捕捉了异常,那么编译器会认为这个异常得到了解决,因此之后的代码正常执行

  • 注意事项

①一个try必须搭配catch或finally中的其中一个。

因为try的作用是提出可能抛出异常的语句块,而catch与finally决定了之后的操作,如果不搭配其中一个,这个try就失去了意义

                                                           仅含try,编译器警告我们插入finally完善结构

②一个try下可以有多个catch,但catch要按其捕获的异常类型由子类到父类的顺序编写

public class Unusual{
	public static void main(String[] args){
		try{
                    String name=null;
                    System.out.println(name.length());//可能出现异常的语句
                }catch(NullPointerException e){       //首先catch NullPointerException异常
                    System.out.println("NUll");       //捕获成功后输出“NULL”
		}catch(ArithmeticException e){        //再捕获ArithmeticException异常
                    System.out.println("0");          //捕获成功后输出“0”
		}catch(Exception e){                  //最后捕获Exception(一切异常)
                    System.out.println("other"+e);    //捕获成功后输出“other”+e
		}
	}
}

虽然这些catch看起来是并列的,但实际上会从上往下执行,而try catch语句的执行逻辑为:

try语句块中的代码可能会引发多种类型的异常,当引发异常时,会按顺序查看每个 catch 语句,并执行第一个与异常类型匹配的catch语句,其后 catch 语句被忽略。

因此,如果我们先捕获“更大”的异常类型,那么如果语句符合这个异常类型,catch语句就会执行,其后对“更小”的异常类型的捕获就会被忽略,那么之后的语句其实已经没有了意义,并且由于这样子导致捕获不够精确,返回的方法也不一定是最适合这个异常的解决方法。

由于第一个catch已经生效,之后的catch失去作用,因此这段代码的执行结果为”NULL“,除了多写的catch做了无用功外,try中剩下的可能异常的语句没有得到捕捉,虽然程序运行没有问题,但是程序员无法判断它们到底是不是异常,可能导致之后编写代码出现问题。

③无论try中是否有异常发生,finlly中的代码总会执行,一般用于释放资源

public class Unusual {
	public static void main(String[] args) {
		try {
		    System.out.println(1/0);            //0做分母,语句出现异常
		}catch(Exception e) {
		    System.out.println("other"+e);
		}finally{
		    System.out.println("zhixing");
		}
		try{
		    System.out.println(1/1);            //实际上这个语句并没有异常
		}catch(Exception e){
		    System.out.println("other"+e);
		}finally{
		    System.out.println("zhixing");
		}
	}
}

执行结果为

我们可以看到,无论try后的语句是否异常,finally语句都执行了。

  • 异常处理的弊端以及解决 

在异常处理时,编译器会将异常信息打印控制台,而控制台会存入一段缓存,缓存有大小。当缓存满了,但是异常信息源源不断,则会将最先进入缓存的异常信息移除,意味着无法全面的发现程序运行期间出现的问题,为了全面收集系统运行期间出现的所有异常信息,log4j诞生了,与存入缓存不同,log4j将所有的异常信息输出到一个文件中,因为文件在硬盘上,可以认为无限大,因此异常信息可以完全得到保存。

  • log4j的使用方法

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值