您的位置 首页 java

初识java—(四十七)异常处理

Java 的异常机制主要依赖于try、catch、finally、throw和throws五个关键字,其中try关键字后面紧跟着一个花括号括起来的代码块,它里面放置可能会引发异常的代码块。catch后面对应异常类型和一个代码块,用于表明该catch块用于处理这种类型的代码块,多个catch块后面还可以跟一个finally块,用于回收在try块里打开的物理资源,异常机制会保证finally块总会被执行。 throws 关键字主要在方法签名中使用,用于声明该方法可能抛出的异常;而throw用于抛出一个实际的异常,throw可以单独作为语句使用,抛出一个具体的异常对象。

10.1 异常概述

异常处理已经成为衡量一门语言是否成熟的标准之一,目前的主流编程语言如C++,C#, Ruby 等大都提供了异常处理机制。增加异常处理机制后的程序有更好的容错性,更加健壮。但不代表你这个代码就要随便写了。比如说下面这个代码。

举例1:

public static void main(String[] args) {

List<String> list = new ArrayList<String>();

list.add(“abc”);

list.add(“def”);

try {

for ( int i=0;i<4;i++){

System. out .println(list.get(i));

}

} catch (IndexOutOfBounds Exception e) {

System. out .println(“已经超出了集合的范围”);

}

}

10.2 异常处理机制

Java的异常处理机制可以让程序具有极好的容错性,让程序更加健壮。当程序出现意外情形时,系统会自动生成一个Exception对象来通知程序,从而实现将“业务功能实现代码”和“错误处理代码”分离,提供更好的可读性。

10.2.1 使用try…catch捕获异常

在Java中提出了一种假设:如果程序可以顺利完成,那就“一切OK”,把系统的业务实现代码放在try块中定义,所有的异常处理逻辑放在catch块中进行处理。下面是Java异常处理机制的语法规则。

try{

//业务实现代码

}catch(ExceptionClass1 e1){

//错误处理代码

}catch(ExceptionClass2 e2){

//错误处理代码

}finally{

//始终会执行的代码

}

Try块后可以有多个catch块,这是为了针对不同的异常类提供不同的异常处理方式。当系统发生不同的意外情况时,系统会生成不同的异常对象,Java运行时就会根据该异常对象所属的异常类来决定使用哪个catch块来处理。

举例1:

public static void main(String[] args) {

List<String> list = new ArrayList<String>();

list.add(“abc”);

list.add(“def”);

list.add( null );

try {

for ( int i=0;i<4;i++){

list.get(i).equals(“abc”);

System. out .println(list.get(i));

}

} catch (IndexOutOfBoundsException e) {

System. out .println(“索引值越界异常”);

} catch (NullPointerException e){

System. out .println(“空指针异常处理”);

} finally {

System. out .println(“始终会被执行的代码块”);

}

}

10.2.2 异常类的继承体系

Java提供了丰富的异常类,这些异常类之间有严格的继承关系,如下图所示:

在Java中把所有的非正常情况分为两种:异常(Exception)和错误(Error),他们都继承Throwable父类。Error错误,一般是指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这种错误无法恢复或不能捕获,将导致应用程序中断。通常应用程序无法处理这些错误,因此应用程序不能试图使用catch块来捕获Error对象,在定义方法时也无须其throws子句中声明该方法可能抛出Error及其任何子类。

10.2.3 访问异常信息

如果程序需要在catch块中访问异常对象的相关信息,则可以通过访问catch块后的异常形参来获得。当Java运行时决定调用某个catch块来处理该异常对象时,会将异常对象赋给catch块后的异常参数,程序即可通过该参数来获得异常的相关信息。

所有异常对象都包含了如下几个常用方法。

Ø getMessage():返回该异常的详细描述 字符串

Ø printStackTrace():将该异常的跟踪栈信息输出到标准错误输出。

Ø printStackTrace(PrintStream s):将该异常的跟踪栈信息输出到指定输出流中。

Ø getStackTrace():返回该异常的跟踪栈信息。

举例1:

public static void main(String[] args) {

List<String> list = new ArrayList<String>();

list.add(“abc”);

list.add(“def”);

list.add( null );

try {

for ( int i=0;i<4;i++){

list.get(i).equals(“abc”);

System. out .println(list.get(i));

}

} catch (IndexOutOfBoundsException e) {

System. out .println(“已经超出了集合的范围”);

} catch (NullPointerException e){

e.printStackTrace();

System. out .println(e.getMessage());

System. out .println(“空指针异常处理”);

} finally {

System. out .println(“始终会被执行的代码块”);

}

}

输出信息:

10.2.4 使用finally回收资源

程序在try块里打开了一些物理资源,比如:数据库连接、网络连接、和磁盘文件等,这些物理资源都必须显示回收。

如果在try块的某条语句引起了异常,该语句后的其他语句通常不会获得执行的机会,这将导致该语句之后的资源回收语句得不到执行。如果在catch块里进行资源回收,但catch块完全有可能得不到执行,这将导致不能及时回收这些物理资源。

为了保证一定能回收try块中打开的物理资源,异常处理机制提供了finally块。不管try块中的代码是否出现异常,也不管哪一个catch块被执行,甚至在try块或者catch块中执行了return语句,finally块总会被执行。因此回收资源执行语句应该在finally块中执行。

举例1:

public static void main(String[] args) {

FileInputStream fis = null ;

try {

fis = new FileInputStream(“./a.txt”);

} catch (Exception e) {

e.printStackTrace();

return ;

} finally {

try {

fis.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

10.2.5 使用throws声明抛出异常

使用throws声明抛出异常的思路是,当前方法不知道如何处理这种类型的异常,该异常应该由上一级调用者处理;如果main方法也不知道如何处理这种类型的异常,也可以使用throws声明抛出异常,该异常将交给 JVM 处理。JVM对异常的处理方法是,打印异常的跟踪栈信息,并终止程序执行。

举例1:

public void deal File () throws Exception{

FileInputStream fis = null ;

try {

fis = new FileInputStream(“./a.txt”);

} catch (Exception e) {

fis.close();

e.printStackTrace();

}

}

public static void main(String[] args) throws Exception {

Test Test = new Test();

test.dealFile();

}

10.2.6 使用throw抛出异常

如果需要在程序中自主的抛出异常,则应该使用throw语句,throw语句可以单独使用,throw语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一个异常实例。

举例1:

public static void main(String[] args){

for ( int num=5;num>=0;num–){

try {

if (num<2){

throw new Exception(“数字的值小于2了,停止运行”);

}

} catch (Exception e) {

System. out .println(“======”);

System. out .println(e.getMessage());

}

}

System. out .println(“最终执行完成”);

}

异常处理小总结

生活中的异常:出去玩,有严重问题,一般问题,玩之前出现问题,玩的过程中出现问题。

程序的异常: Throwable

严重问题:Error–我们不处理,这种问题一般都是很严重的问题,比如说:内存溢出

一般问题:Excepton

编译期问题:不是RuntimeException:必须进行处理的异常,不处理,编译不会通过。(这就是咱要处理问题)

运行期问题:RuntimeException :无法直接处理,代码问题,需要修改代码

程序出现问题时,我们不处理,最终 jvm会进行默认的处理

把异常的名称、原因以及出现的问题等信息输出在控制台上,同时会结束程序,不再执行以后的代码。

我们是如何处理的:

A: try…catch…finally

注意:

(1) try 里边的代码越少越好:放在try里边就要走异常处理机制,jvm就一些新的资源来处理问题。

(2) catch里边必须有内容: eg : TestTryCatch1

(3) 多个catch语句时:一旦try里面出现了问题,就会在这里把问题给抛出去,然后和catch里面的问题进行匹配,一旦有匹配的,就执行catch里面的处理,就直接结束了try…catch,继续执行后面的语句,而不会执行try里边的其它语句 。eg :TestTryCatch2

(4) 如果在一个try中不知道是哪里出现了问题,是出现是什么类型的问题?可以在最后一个catch中添加一个Exception的“异常类型”

(5) catch里边的“异常类型”,有明确的要明确。如果直接写Exception的话,jvm会从Exception中来进行查找。而且Exception“异常类型”必须是写在最后边!也就是说,父类必须在最后边! eg: TestTryCatch2

讲解一下编译时异常与运行时异常的区别:

(1) 编译时异常:java程序必须显示处理,否则程序就会发生错误,无法通过编译: eg: TestTryCatch3

(2) 运行时异常:无需显示处理,也可以和编译时异常一样处理

异常中要了解的几个方法:

所有异常对象都包含了几个常用方法:这几个方法是哪里的? Throwable

Ø getMessage():返回该异常的详细描述字符串。

Ø printStackTrace():将该异常的跟踪栈信息输出到标准错误输

Ø printStackTrace(PrintStream s):将该异常的跟踪栈信息输出到指定输出流中。(咱用这个!)

u 这的内容和jvm默认处理输出一样,但是咱们可以接着执行try..catch后面的内容。 eg .TestTrycatch4

Finally:

是异常处理的一部分,用于释放资源。

注意:finally中的代码一般会被执行,但是如果执行到finally之前jvm退出了,就不能执行了。

eg:TestFinally

final,finally, finalize 的区别:

final:最终的意思,可以修饰类(不能被继承),成员变量,成员方法(不能被被重写)。

finally:是异常处理的一部分,用于释放资源。finally中的代码一般会被执行,但是如果执行到finally之前jvm退出了,就不能执行了。

finalize:是Object类中的一个方法,用于垃圾回收。

B: thorws 抛出

eg: TestThrows TestThrow

throws和throw的区别:

l throws

• 用在方法声明后面,跟的是异常类名

• 可以跟多个异常类名,用逗号隔开

• 表示抛出异常,由该方法的调用者来处理

• throws表示出现异常的一种可能性,并不一定会发生这些异常

l throw

• 用在方法体内,跟的是异常对象名

• 只能抛出一个异常对象名

• 表示抛出异常,由方法体内的语句处理

• throw则是抛出了异常,执行throw则一定抛出了某种异常

如果catch里面有return语句,请问finally里面的代码还会执行吗?如果会,请问在return之前还是之后 ?

答案:会执行,之前执行。

文章来源:智云一二三科技

文章标题:初识java—(四十七)异常处理

文章地址:https://www.zhihuclub.com/182153.shtml

关于作者: 智云科技

热门文章

网站地图