详解Java中Checked Exception与Runtime Exception 的区别
详解Java中CheckedException与RuntimeException的区别
Java里有个很重要的特色是Exception,也就是说允许程序产生例外状况。而在学Java的时候,我们也只知道Exception的写法,却未必真能了解不同种类的Exception的区别。
首先,您应该知道的是Java提供了两种Exception的模式,一种是执行的时候所产生的Exception(RuntimeException),另外一种则是受控制的Exception(CheckedException)。
所有的CheckedException均从java.lang.Exception继承而来,而RuntimeException则继承java.lang.RuntimeException或java.lang.Error(实际上java.lang.RuntimeException的上一层也是java.lang.Exception)。
当我们撰写程序的时候,我们很可能会对选择某种形式的Exception感到困扰,到底我应该选择RuntimeException还是CheckedException?
其实,在运作上,我们可以通过Class的Method如何产生某个Exception以及某个程序如何处理这个被产生来的Exception来了解它们之间的差异。
首先我们先建立一个Exception
publicclassCExceptionextendsException { publicCException(){} publicCException(Stringmessage) { super(message); } }
然后我们撰写一个可能产生CException的Class
publicclasstestException { publicvoidmethod1()throwsCException { thrownewCException("TestException"); } publicvoidmethod2(Stringmsg) { if(msg==null) { thrownewNullPointerException("Messageisnull"); } } publicvoidmethod3()throwsCException { method1(); } //以下省略 //... }
在这三个method中,我们看到了method1和method2的程序码内都会产生Exception,但method3的程序码中(大括号内),并没产生Exception,但在method3的定义中,暗示了这个method可能产生CException。
呼叫method1()的程序,必须将method1()包含在try与catch中,如:
publicclassruntest { //.... publicstaticvoidmain(Stringargv[]) { testExceptionte=newtestException(); try { te.method1(); } catch(CExceptionce) { //.... } } //... }
虽然包含在try与catch中,并不表示这段程序码一定会收到CException,但它的用意在于提醒呼叫者,执行这个method可能产生的意外,而使用者也必须要能针对这个意外做出相对应的处理方式。
当使用者呼叫method2()时,并不需要使用try和catch将程序码包起来,因为method2的定义中,并没有throws任何的Exception,如:
publicclassruntest { //.... publicstaticvoidmain(Stringargv[]) { testExceptionte=newtestException(); //不会产生Exception te.method2("Hello"); //会产生Exception te.method2(null); } //... }
程序在执行的时候,也不见得会真的产生NullPointerException,这种Exception叫做runtimeexception也有人称为uncheckedexception,产生RuntimeException的method(在这个范例中是method2)并不需要在宣告method的时候定义它将会产生哪一种Exception
在testException的method3()中,我们看到了另外一种状况,也就是method3里呼叫了method1(),但却没有将method1包在try和catch之间。相反,在method3()的定义中,它定义了CException,实际上就是如果method3收到了CException,它将不处理这个CException,而将它往外丢。当然,由于method3的定义中有throwsCException,因此呼叫method3的程序码也需要有trycatch才行。
因此从程序的运作机制上看,RuntimeException与CheckedException不一样,然而从逻辑上看,RuntimeException与CheckedException在使用的目的上也不一样。
一般而言,CheckedException表示这个Exception必须要被处理,也就是说程序设计者应该已经知道可能会收到某个Exception(因为要trycatch住),所以程序设计者应该能针对这些不同的CheckedException做出不同的处理。
而RuntimeException通常会暗示着程序上的错误,这种错误会导致程序设计者无法处理,而造成程序无法继续执行下去。
看看下面的例子:
Stringmessage[]={"message1","message2","message3"}; System.out.println(message[3]);
这段程序码在Compile时并没问题,但在执行时则会出现ArrayIndexOutOfBoundException的例外,在这种状况下,我们亦无法针对这个RuntimeException做出有意义的动作,这就像是我们呼叫了testException中的method2,却引发了它的NullPointerException一样,在这种状况下,我们必须对程序码进行修改,从而避免这个问题。
因此,实际上我们应该也必须要去抓取所有的CheckedException,同时最好能在这些CheckedException发生的时候做出相对应的处理,好让程序能面对不同的状况。
然而对于RuntimeException,有些人建议将它catch住,然后导向其它地方,让程序继续执行下去,这种作法并非不好,但它会让我们在某些测试工具下认为我们的程序码没有问题,因为我们将RuntimeException"处理"掉了,事实却不然!譬如很多人的习惯是在程序的进入点后用个大大的trycatch包起来,如:
publicclassruntest1 { publicstaticvoidmain(Stringargv[]) { try { //... } catch(Exceptione) { } } }
在这种情况下,我们很可能会不知道发生了什么Exception或是从哪一行发出的,因此在面对不同的CheckedException时,我们可已分别去trycatch它。而在测试阶段时,如果碰到RuntimeException,我们可以让它就这样发生,接着再去修改我们的程序码,让它避免RuntimeException,否则,我们就应该仔细追究每一个Exception,直到我们可以确定它不会有RuntimeException为止!
对于CheckedException与RuntimeException,我想应该有不少人会有不同的观点,无论如何,程序先要能执行,这些Exception才有机会产生。因此,我们可以把这些Exception当成是Bug,也可以当成是不同的状况(CheckedException),或当成是帮助我们除错的工具(RuntimeException),但前提是我们需要处理这些Exception,如果不处理,那么问题或状况就会永远留在那里。
以上就是Java中CheckedException与RuntimeException的区别,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!