本文分享自华为云社区《Java知识点问题精选之异常机制》,原作者:breakDrawJava异常指的是程序运行时可能出现的一些错误,如:找不到文件,网络连接失败、非法参数等。异常是程序执行过程中发生的事件,中断了正在执行的程序的正常指令流。Java通过API中Throwable类的众多子类来描述各种异常。因此,Java异常是对象,是Throwable子类的实例,它描述了一段代码中发生的错误情况。当条件产生时,错误将引发异常。Java技术需要对运行时异常、错误或可检查异常进行不同的异常处理。异常系统分类Q:Throwable和Error的关系A:Throwable是Error(错误)的基类,也是Exception的基类。一张图很好的展示了常见的异常和错误Q:Error和Exception的关系A:Error是一般的是会直接导致jvm出错的错误,比如Java虚拟机运行出错等如果当前线程发生,将无法继续运行。Excpetion是程序本身可以处理的异常。发生后,仍可正常使用。Q:Error可以用catch捕获吗?A:只要Throwable和它的子类能throw和catch就可以了。但是不建议捕获Error。异常系统也可以分为这两类:非检查异常(non-checkedexception),也称为运行时异常(RuntimeException),比如常见的NullPointerException、IndexOutOfBoundsException。对于运行时异常,java编译器不需要异常捕获处理或抛出语句,由程序员自己决定。检查异常(checkexception,compilationexception)也叫非运行时异常(除了runtimeexception就是non-runtimeexception),java编译器强制程序员去捕捉和处理,比如常见的IOExeption和SQLException。如果没有捕获或抛出非运行时异常,则编译不会通过。异常捕获并返回Q:return-finallytrap1:最终可以通过修改变量来更新返回变量值intf(){inta=1;try{returna;}finally{a=2;}}A:不,f返回1。Q:return-finally陷阱2:当finally中也有return时,应该返回哪一个?intf(){try{return1;}finally{return2;}}A:返回finally,return2。问:什么情况下finally块中的步骤可以不执行?A:只有在finally退出jvm之前调用System.exit(0)才能finally不执行。问:接下来会发生什么?try{start();}catch(Exceptionex){System.out.println("catchException");}catch(RuntimeExceptionre){System.out.println("catchRuntimeException");}A:直接编译错.catch将按顺序排列,如果匹配到一个,则不会再匹配。因此,编译器认识到RuntimeExcpetion永远不会被捕获,并提前报告错误。Q:抛出异常的时候,在finally中return,还会抛出异常吗?staticintf(){try{inta=1/0;returna;}catch(Exceptione){thrownewRuntimeException(e);}finally{return-1;}}publicstaticvoidmain(String[]args){System.out.println(f());}A:不,返回-1。即finally中return会中断throw,所以finally中永远不要做return操作。关于checkedexceptions的问题Q:子类重写基类方法时,会不会抛出基类方法不存在的异常?像下面这样:classA{voidf()throwsIOException{}}classBextendsA{voidf()throwsIOException,SQLException{}}A:不行,直接编译报错。即子类重写父类方法时,throws关键字后面的异常必须小于等于父类方法的异常。Q:finally调用资源的close时,也会抛出checkedexception。除了try-catchinfinally,我还能做什么?像下面这样,终于有一个难看的陷阱:TryWithResourcetryWithResource=newTryWithResource();尝试{System.out.println(tryWithResource.age);}catch(Exceptione){e.printStackTrace();}最后{try{tryWithResource.close();}catch(Exceptione){e.printStackTrace();}}A:如果是JDK1.7,可以使用try-with-resource语法。资源类需要实现AutoCloseable接口,在尝试时跟上try括号后的资源创建,如下:publicstaticvoidmain(String[]args){try(TryWithResourcetryWithResource=newTryWithResource()){系统输出。println(tryWithResource.age);}catch(Exceptione){e.printStackTrace();}}这样就不用写finally了,finally+close会被编译器自动给我们加上。Q:线程抛出异常如何捕获?A:实现异常处理接口MyUncheccedExceptionhandlerpublicclassMyUncheccedExceptionhandlerimplementsUncaughtExceptionHandler{@OverridepublicvoiduncaughtException(Threadt,Throwablee){System.out.println("Catch异常处理方法:"+e);}}然后设置实现类到相应的线程。Threadt=newThread(newExceptionThread());t。setUncaughtExceptionHandler(newMyUncheckedExceptionhandler());t.start();
