java中异常处理(12、Java基础-异常处理)java教程 / Java异常处理与调试技巧...

wufei123 发布于 2024-02-18 阅读(80)

1、Java异常类层次结构

Throwable:有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类Error:一般表示代码运行时 JVM 出现问题通常有 VirtualMachineError(虚拟机运行错误)、NoClassDefFoundError(类定义错误)等。

比如 OutOfMemoryError:内存不足错误;StackOverflowError:栈溢出错误此类错误发生时,JVM 将终止线程这些错误是非受检异常,非代码性错误因此,当此类错误发生时,应用程序不应该去处理此类错误。

按照Java惯例,我们不应该实现任何新的Error子类的 VirtulMachineError: StackOverFlowError OutOfMemoryError ... Exception:程序本身可以捕获并且可以处理的异常。

非运行时异常 (编译异常): IOException 操作输入流和输出流时可能出现的异常 EOFException 文件异常结束 FileNotFoundException 文件未找到异常。

SocketException 网络通信异常 SQLException 操作数据库异常 NoSuchMethodException 方法未找到抛出的异常 ParseException 解析时出现异常

ClassNotFoundException 找不到类异常 ... RuntimeException: NullPointerException 空指针异常 ArrayIndexOutOfBoundException 数组索引越界异常

ArithmeticException 算术条件异常 IllegalArgumentException 非法参数异常 ClassCastException 对象强制转换异常 UnsupportedOperationException 不支持请求的操作异常

...2、受检异常和非受检异常unchecked exception:非受检异常(编译器不强制要求处置的异常)包括运行时异常(RuntimeException与其子类)和错误(Error)这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

Java编译器不强制要求处理 也就是说,这类异常在程序中,可以进行处理,也可以不处理checked exception:受检异常(编译器要求必须处置的异常)除了RuntimeException及其子类以外,其他的Exception类及其子类都属于受检异常。

这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过3、java的异常处理机制捕获并处理:捕捉异常通过try-catch语句或者try-catch-finally语句实现。

try{// 可能会发生异常的程序代码 }catch(Exception1e){// 捕获并处置try抛出的异常类型Exception1 }catch(Exception2e){// 捕获并处置try抛出的异常类型Exception2

}finally{// 无论是否发生异常,都将执行的语句块 }a、一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常简单地说,异常总是先被抛出,后被捕捉的b、一旦某个catch捕获到匹配的异常类型,将进入异常处理代码。

一经处理结束,就意味着整个try-catch语句结束其他的catch子句不再有匹配和捕获异常类型的机会此处Exception1不能是Exception2的父类c、try后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。

d、当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行在以下几种特殊情况下,finally块不会被执行: 1)在finally语句块中发生了异常 2)在前面的代码中用了System.exit()退出程序。

3)程序所在的线程死亡向上抛出:当出现异常没办法处理时可以向上抛出异常throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。

两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由方法去处理异常,真正的处理异常由此方法的上层调用处理(1) throws抛出异常: 1)必须声明方法可抛出的任何checked exception。

即如果一个方法出现受检异常,要么用try-catch语句捕获,要么用throws子句声明将它抛出,否则会导致编译错误 2)仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常 3)若覆盖一个方法,则不能声明与覆盖方法不同的异常。

声明的任何异常必须是被覆盖方法所声明异常的同类或子类 4) throws后面可以跟多个异常类型,多个之间用逗号隔开publicbooleanmerge()throwsIOException{File。

[]files=source.listFiles(filter);try(SequenceInputStreamsis=FileUtil.getSequenceInputStream(files,comparator

)){Pathtarget=Paths.get(source.getCanonicalPath(),fileName);Files.copy(sis,target);}returntrue;}(2) throw抛出异常

1)throw总是出现在函数体中,用来抛出一个Throwable或者其子类的实例对象2)如果抛出了检查异常,则还应该在方法头部声明方法可能抛出的异常类型该方法的调用者也必须检查处理抛出的异常if(flag

){thrownewRuntimeException("运行错误");}4、try、catch、finally语句块的执行顺序1)当try没有捕获到异常时:try语句块中的语句逐一被执行,程序将跳过catch语句块,执行finally语句块和其后的语句。

2)当try捕获到异常,但没有处理此异常的情况:程序将跳过try出错后的语句块,执行finally语句块和其后的语句 3)当try捕获到异常,并正确处理该异常:在try语句块中是按照顺序来执行的,当执行到某一条语句出现异常时,程序将跳到catch语句块,并与catch语句块逐一匹配,找到与之对应的处理程序,其他的catch语句块将不会被执行,而try语句块中,出现异常之后的语句也不会被执行,catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句。

*:当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行publicstaticvoidmain(String[]args){intresult=getResult。

();Console.log("main result : {0}",result);}privatestaticintgetResult(){intresult;try{thrownewRuntimeException

();}catch(Exceptione){result=6;returnresult;}finally{result=7;Console.log("finally result : {0}",result

);}}// 运行结果: finallyresult:7mainresult:6*:当在try块或catch块中遇到return语句,在finally中也有return语句时,finally中的return会覆盖catch中的return。

publicstaticvoidmain(String[]args){intresult1=getResult1();Console.log("main result1 : {0}",result1);

}privatestaticintgetResult1(){intresult;try{thrownewRuntimeException();}catch(Exceptione){result=6;return

result;}finally{result=7;Console.log("finally result1 : {0}",result);returnresult;}}// 运行结果: finallyresult1

:7mainresult1:75、java7中的异常改进多重异常捕获在try catch异常中,一个catch可以写多个异常类型,用"|"隔开try{......}catch(ClassNotFoundException

|SQLExceptionex){......}try-with-resource自动关闭资源的try: 关闭的资源类需要实现AutoCloseable()或者Closeable()接口的close()方法

// 在java7之前需要这么写 FileInputStreamfis=null;try{fis=newFileInputStream(newFile("aa.txt"));}catch(FileNotFoundException

e){e.printStackTrace();}finally{try{if(fis!=null){fis.close();}}catch(IOExceptione){e.printStackTrace

();}}// java7之后可以这样写 try(FileInputStreamfis=newFileInputStream(newFile("aa.txt"))){fis.read();}catch(

IOExceptione){e.printStackTrace();}精准的重新抛出异常在 Java7之前,如果捕捉到一个异常,重新抛出的异常类型只能与原异常完全相同这导致代码不精确,Java 7修复了这个问题。

在 Java 7 之前,下面的代码无法编译classBaseExceptionextendsException{}classDerivedExceptionextendsBaseException{}static

voidcatcher()throwsDerivedException{try{thrownewDerivedException();}catch(BaseExceptione){throwe;}}6、异常处理建议

只在必要使用异常的地方才使用异常,不要用异常去控制程序的流程切忌使用空catch块,捕获类异常就应该处理它尽量避免检查异常的使用,如果确实该异常情况的出现很普遍,需要提醒调用者注意处理的话,就使用检查异常;否则使用非检查异常。

注意catch块的顺序,不要把上层类的异常放在最前面的catch块,应该优先捕获最具体的异常避免重复多次处理同一异常,如果要记录日志信息,可以在最终处理异常的地方记录不要直接捕获 Throwable 类。

包装异常时不要抛弃原始的异常信息。 finally块必须对资源对象、流对象进行关闭,有异常也要做try-catch。如果JDK7及以上,应该使用try-with-resources方式。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

河南中青旅行社综合资讯 奇遇综合资讯 盛世蓟州综合资讯 综合资讯 游戏百科综合资讯 新闻53266