javatry()变量_【Java学习笔记之三⼗三】详解Java中
try,catch,fi。。。
这⼀篇我们将会介绍java中try,catch,finally的⽤法
以下先给出try,catch⽤法:
try{
//需要被检测的异常代码
}
catch(Exception e)
{
//异常处理,即处理异常代码
}
finally{//⼀定会被执⾏的代码
}
代码区如果有错误,就会返回所写异常的处理。
⾸先要清楚,如果没有try的话,出现异常会导致程序崩溃。⽽try则可以保证程序的正常运⾏下去,⽐如说:
try{int i = 1/0;
}catch(Exception e)
{
........
}
⼀个计算的话,如果除数为0,则会报错,如果没有try的话,程序直接崩溃。⽤try的话,则可以让程序运⾏下去,并且输出为什么出错!
try catch 是捕捉try部分的异常,当你没有trycatch的时候,如果出现异常则程序报错,加上try,catch,出现异常程序正常运⾏,只是把错误信息存储到Exception⾥,所以catch是⽤来提取异常信息的,你可以在catch部分加上⼀句System.out.println(e.ToString());,如果出现异常可以把异常打印出来~~
java的异常处理机制(try…catch…finally)
1 引⼦
try…catch…finally恐怕是⼤家再熟悉不过的语句了,⽽且感觉⽤起来也是很简单,逻辑上似乎也是很容易理解。不过,我亲⾃体验的“教训”告诉我,这个东西可不是想象中的那么简单、听话。不信?那你看看下⾯的代码,“猜猜”它执⾏后的结果会是什么?不要往后看答案、也不许执⾏代码看真正答案哦。如果你的答案是正确,那么这篇⽂章你就不⽤浪费时间看啦。
1 public classTestException
2 {
3 publicTestException()
4 {
5 }
6 boolean testEx() throwsException
7 {
8 boolean ret = true;
9 try
10 {11 ret =testEx1();12 }13 catch(Exception e)14 {15 System.out.println("testEx, catch exception");16 ret = false;17 throwe;18 }19 finally
20 {21 System.out.println("testEx, finally; return value=" +ret);22 returnret;23 }24 }25 boolean testEx1()
throwsException26 {27 boolean ret = true;28 try
29 {30 ret =testEx2();31 if (!ret)32 {33 return false;34 }35 System.out.println("testEx1, at the end of try");36 returnret;37 }38 catch(Exception e)39 {40 System.out.println("testEx1, catch exception");41 ret = false;42 throwe;43 }44 finally
45 {46 System.out.println("testEx1, finally; return value=" +ret);47 returnret;48 }49 }50 boolean testEx2()
throwsException51 {52 boolean ret = true;53 try
54 {55 int b = 12;56 intc;57 for (int i = 2; i >= -2; i--)58 {59 c = b /i;60 System.out.println("i=" +i);61 }62 return true;63 }64 catch(Exception e)65 {66 System.out.println("testEx2, catch exception");67 ret = false;68 throwe;69 }70 finally
71 {72 System.out.println("testEx2, finally; return value=" +ret);73 returnret;74 }75 }76 public static voidmain(String[] args)77 {78 TestException testException1 = newTestException();79 try
80 {stEx();82 }83 catch(Exception e)84 {85 e.printStackTrace();86 }87 }88 }
你的答案是什么?是下⾯的答案吗?
i=2i=1testEx2,catchexception
testEx2,finally; return value=falsetestEx1,catchexception
testEx1,finally; return value=falsetestEx,catchexception
testEx,finally; return value=false
如果你的答案真的如上⾯所说,那么你错啦。^_^,那就建议你仔细看⼀看这篇⽂章或者拿上⾯的代码按各种不同的情况修改、执⾏、测试,你会发现有很多事情不是原来想象中的那么简单的。
现在公布正确答案:
i=2i=1testEx2,catchexception
testEx2,finally; return value=falsetestEx1,finally; return value=falsetestEx,finally; return value=false
2 基础知识
2.1 相关概念
例外是在程序运⾏过程中发⽣的异常事件,⽐如除0溢出、数组越界、⽂件不到等,这些事件的发⽣将阻⽌程序的正常运⾏。为了加强程序的鲁棒性,程序设计时,必须考虑到可能发⽣的异常事件并做出相应的处理。C语⾔中,通过使⽤if语句来判断是否出现了例外,同时,调⽤函数通过被调⽤函数的返回值感知在被调⽤函数中产⽣的例外事件并进⾏处理。全程变量ErroNo常常⽤来反映⼀个异常事件的类型。但是,这种错误处理机制会导致不少问题。
Java通过⾯向对象的⽅法来处理例外。在⼀个⽅法的运⾏过程中,如果发⽣了例外,则这个⽅法⽣成代表该例外的⼀个对象,并把它交给运⾏时系统,运⾏时系统寻相应的代码来处理这⼀例外。我们把⽣成例外对象并把它提交给运⾏时系统的过程称为抛弃(throw)⼀个例外。运⾏时系统在⽅法的调⽤栈中查,从⽣成例外的⽅法开始进⾏回朔,直到到包含相应例外处理的⽅法为⽌,这⼀个过程称为捕获(catch)⼀个例外。
2.2 Throwable类及其⼦类
⽤⾯向对象的⽅法处理例外,就必须建⽴类的层次。类 Throwable位于这⼀类层次的最顶层,只有它的后代才可以做为⼀个例外被抛弃。图1表⽰了例外处理的类层次。
从图中可以看出,类Throwable有两个直接⼦类:Error和Exception。Error类对象(如动态连接错误等),由Java虚拟机⽣成并抛弃(通常,Java程序不对这类例外进⾏处理);Exception类对象是Java程序处理或抛弃的对象。它有各种不同的⼦类分别对应于不同类型的例外。其中类RuntimeException代表运⾏时由Java虚拟机⽣成的例外,如算术运算例外ArithmeticException(由除0错等导致)、数组越界例外ArrayIndexOutOfBoundsException等;其它则为⾮运⾏时例外,如输⼊输出例外IOException等。Java编译器要求Java程序必须捕获或声明所有的⾮运⾏时例外,但对运⾏时例外可以不做处理。
2.3 异常处理关键字
Java的异常处理是通过5个关键字来实现的:try,catch,throw,throws,finally。JB的在线帮助中对这⼏个关键字是这样解释的:
Throws:  Lists the exceptions a method could throw.
Throw:  Transfers control of the method to the exception handler.
Try:    Opening exception-handling statement.
Catch:  Captures the exception.
Finally: Runs its code before terminating the program.
2.3.1 try语句
try语句⽤⼤括号{}指定了⼀段代码,该段代码可能会抛弃⼀个或多个例外。
2.3.2 catch语句
catch语句的参数类似于⽅法的声明,包括⼀个例外类型和⼀个例外对象。例外类型必须为Throwable类的⼦类,它指明了catch语句所处理的例外类型,例外对象则由运⾏时系统在try所指定的代码块中⽣
成并被捕获,⼤括号中包含对象的处理,其中可以调⽤对象的⽅法。
catch语句可以有多个,分别处理不同类的例外。Java运⾏时系统从上到下分别对每个catch语句处理的例外类型进⾏检测,直到到类型相匹配的catch语句为⽌。这⾥,类型匹配指catch所处理的例外类型与⽣成的例外对象的类型完全⼀致或者是它的⽗类,因此,catch语句的排列顺序应该是从特殊到⼀般。
也可以⽤⼀个catch语句处理多个例外类型,这时它的例外类型参数应该是这多个例外类型的⽗类,程序设计中要根据具体的情况来选择catch语句的例外处理类型。
2.3.3 finally语句
try所限定的代码中,当抛弃⼀个例外时,其后的代码不会被执⾏。通过finally语句可以指定⼀块代码。⽆论try所指定的程序块中抛弃或不抛弃例外,也⽆论catch语句的例外类型是否与所抛弃的例外的类型⼀致,finally所指定的代码都要被执⾏,它提供了统⼀的出⼝。通常在finally语句中可以进⾏资源的清除⼯作。如关闭打开的⽂件等。
2.3.4 throws语句
throws总是出现在⼀个函数头中,⽤来标明该成员函数可能抛出的各种异常。对⼤多数Exception⼦类
来说,Java
编译器会强迫你声明在⼀个成员函数中抛出的异常的类型。如果异常的类型是Error或 RuntimeException,
或它们的⼦类,这个规则不起作⽤, 因为这在程序的正常部分中是不期待出现的。
如果你想明确地抛出⼀个RuntimeException,你必须⽤throws语句来声明它的类型。
2.3.5 throw语句
throw总是出现在函数体中,⽤来抛出⼀个异常。程序会在throw语句后⽴即终⽌,它后⾯的语句执⾏不到,然后在包含它的所有try块中(可能在上层调⽤函数中)从⾥向外寻含有与其匹配的catch⼦句的try块。
3 关键字及其中语句流程详解
3.1 try的嵌套
你可以在⼀个成员函数调⽤的外⾯写⼀个try语句,在这个成员函数内部,写另⼀个try语句保护其他代
码。每当遇到⼀个try语句,异常的框架就放到堆栈上⾯,直到所有的try语句都完成。如果下⼀级的try语句没有对某种异常进⾏处理,堆栈就会展开,直到遇到有处理这种异常的try语句。下⾯是⼀个try语句嵌套的例⼦。
1 classMultiNest {
2 static voidprocedure() {
3 try{
4 int a = 0;
5 int b = 42/a;
6 } catch(java.lang.ArithmeticException e) {
7 System.out.println("in procedure, catch ArithmeticException: " +e);
8 }
9 }10 public static voidmain(String args[]) {11 try{12 procedure();13 } catch(java.lang. Exception e) {1
4 System.out.println("in main, catch Exception
: " +e);15 }16 }17 }
这个例⼦执⾏的结果为:
in procedure, catch ArithmeticException: java.lang.ArithmeticException: / by zero
成员函数procedure⾥有⾃⼰的try/catch控制,所以main不⽤去处理 ArrayIndexOutOfBoundsExc
eption;当然如果如同最开始我们做测试的例⼦⼀样,在procedure中catch到异常时使⽤throw e;语句将异常抛出,那么main当然还是能够捕捉并处理这个procedure抛出来的异常。例如在procedure函数的catch中的System.out语句后⾯增加throw e;语句之后,执⾏结果就变为:
in procedure, catch ArithmeticException: java.lang.ArithmeticException: /by zero
in main,catch Exception: java.lang.ArithmeticException: / by zero
3.2 try-catch程序块的执⾏流程以及执⾏结果
相对于try-catch-finally程序块⽽⾔,try-catch的执⾏流程以及执⾏结果还是⽐较简单的。
⾸先执⾏的是try语句块中的语句,这时可能会有以下三种情况:
1.如果try块中所有语句正常执⾏完毕,那么就不会有其他的“动做”被执⾏,整个try-catch程序块正常完成。
2.如果try语句块在执⾏过程中碰到异常V,这时⼜分为两种情况进⾏处理:
-->如果异常V能够被与try相应的catch块catch到,那么第⼀个catch到这个异常的catch块(也是离try最近的⼀个与异常V匹配的catch块)将被执⾏;如果catch块执⾏正常,那么try-catch程序块的结果就是“正常完成”;如果该catch块由于原因R突然中⽌,那么try-catch程序块的结果就是“由于原因R突然中⽌(completes
abruptly)”。
-->如果异常V没有catch块与之匹配,那么这个try-catch程序块的结果就是“由于抛出异常V⽽突然中⽌(completes abruptly)”。
3. 如果try由于其他原因R突然中⽌(completes abruptly),那么这个try-catch程序块的结果就是“由于原因R突然中⽌(completes abruptly)”。
3.3 try-catch-finally程序块的执⾏流程以及执⾏结果
try-catch-finally程序块的执⾏流程以及执⾏结果⽐较复杂。
⾸先执⾏的是try语句块中的语句,这时可能会有以下三种情况:
1.如果try块中所有语句正常执⾏完毕,那么finally块的居于就会被执⾏,这时分为以下两种情况:
-->如果finally块执⾏顺利,那么整个try-catch-finally程序块正常完成。
-->如果finally块由于原因R突然中⽌,那么try-catch-finally程序块的结局是“由于原因R突然中⽌(completes abruptly)”
2.如果try语句块在执⾏过程中碰到异常V,这时⼜分为两种情况进⾏处理:
-->如果异常V能够被与try相应的catch块catch到,那么第⼀个catch到这个异常的catch块(也是离try最近的⼀个与异常V匹配的catch块)将被执⾏;这时就会有两种执⾏结果:
-->如果catch块执⾏正常,那么finally块将会被执⾏,这时分为两种情况:
-->如果finally块执⾏顺利,那么整个try-catch-finally程序块正常完成。
-->如果finally块由于原因R突然中⽌,那么try-catch-finally程序块的结局是“由于原因R突然中⽌(compl
etes abruptly)”
-->如果catch块由于原因R突然中⽌,那么finally模块将被执⾏,分为两种情况:
-->如果如果finally块执⾏顺利,那么整个try-catch-finally程序块的结局是“由于原因R突然中⽌(completes abruptly)”。
-->如果finally块由于原因S突然中⽌,那么整个try-catch-finally程序块的结局是“由于原因S突然中⽌(completes abruptly)”,原因R将被抛弃。
(注意,这⾥就正好和我们的例⼦相符合,虽然我们在testEx2中使⽤throw
e抛出了异常,但是由于testEx2中有finally块,⽽finally块的执⾏结果是complete
abruptly的(别⼩看这个⽤得最多的return,它也是⼀种导致complete
abruptly的原因之⼀啊——后⽂中有关于导致complete
abruptly的原因分析),所以整个try-catch-finally程序块的结果是“complete
abruptly”,所以在testEx1中调⽤testEx2时是捕捉不到testEx1中抛出的那个异常的,⽽只能将finally中
的return结果获取到。
如果在你的代码中期望通过捕捉被调⽤的下级函数的异常来给定返回值,那么⼀定要注意你所调⽤的下级函数中的finally语句,它有可能会使你throw出来的异常并不能真正被上级调⽤函数可见的。当然这种情况是可以避免的,以testEx2为例:如果你⼀定要使⽤finally⽽且⼜要将catch中throw的e在testEx1中被捕获到,那么你去掉testEx2中的finally中的return就可以了。
这个事情已经在OMC2.0的MIB中出现过啦:服务器的异常不能完全被反馈到客户端。)
-->如果异常V没有catch块与之匹配,那么finally模块将被执⾏,分为两种情况:
-->如果finally块执⾏顺利,那么整个try-catch-finally程序块的结局就是“由于抛出异常V⽽突然中⽌(completes abruptly)”。
-->如果finally块由于原因S突然中⽌,那么整个try-catch-finally程序块的结局是“由于原因S突然中⽌(completes abruptly)”,异常V将被抛弃。
3.如果try由于其他原因R突然中⽌(completes abruptly),那么finally块被执⾏,分为两种情况:
-->如果finally块执⾏顺利,那么整个try-catch-finally程序块的结局是“由于原因R突然中⽌(completes abruptly)”。
-->如果finally块由于原因S突然中⽌,那么整个try-catch-finally程序块的结局是“由于原因S突然中⽌(completes abruptly)”,原因R将被抛弃。
3.4 try-catch-finally程序块中的return
从上⾯的try-catch-finally程序块的执⾏流程以及执⾏结果⼀节中可以看出⽆论try或catch中发⽣了什么情况,finally都是会被执⾏的,那么写在try或者catch中的return语句也就不会真正的从该函数中跳出了,它的作⽤在这种情况下就变成了将控制权(语句流程)转到finally块中;这种情况下⼀定要注意返回值的处理。
例如,在try或者catch中return false了,⽽在finally中⼜return
true,那么这种情况下不要期待你的try或者catch中的return
false的返回值false被上级调⽤函数获取到,上级调⽤函数能够获取到的只是finally中的返回值,因为try或者catch中的return语句只是转移控制权的作⽤。
3.5 如何抛出异常
如果你知道你写的某个函数有可能抛出异常,⽽你⼜不想在这个函数中对异常进⾏处理,只是想把它抛出去让调⽤这个函数的上级调⽤函数进⾏处理,那么有两种⽅式可供选择:
第⼀种⽅式:直接在函数头中throws SomeException,函数体中不需要try/catch。⽐如将最开始的例⼦中的testEx2改为下⾯的⽅式,那么testEx1就能捕捉到testEx2抛出的异常了。
1 boolean testEx2() throwsException{
2 boolean ret = true;
try catch的使用方法
3 int b=12;
4 intc;
5 for (int i=2;i>=-2;i--){
6 c=b/i;7
System.out.println("i="+i);8 }9 return true;10 }
第⼆种⽅式:使⽤try/catch,在catch中进⾏⼀定的处理之后(如果有必要的话)抛出某种异常。例如上⾯的testEx2改为下⾯的⽅
式,testEx1也能捕获到它抛出的异常:
1 boolean testEx2() throwsException{
2 boolean ret = true;
3 try{
4 int b=12;
5 intc;
6 for (int i=2;i>=-2;i--){
7 c=b/i;8
System.out.println("i="+i);9 }10 return true;11 }catch(Exception e){12 System.out.println("testEx2, catch exception");13 Throw e;14 }15 }
第三种⽅法:使⽤try/catch/finally,在catch中进⾏⼀定的处理之后(如果有必要的话)抛出某种异常。例如上⾯的testEx2改为下⾯的⽅式,testEx1也能捕获到它抛出的异常:
1 boolean testEx2() throwsException{
2 boolean ret = true;
3 try{
4 int b=12;
5 intc;
6 for (int i=2;i>=-2;i--){
7 c=b/i;8
System.out.println("i="+i);9 throw new Exception("aaa");10 }11 return true;12 }catch(java.lang.ArithmeticException e){13 System.out.println("testEx2, catch exception");14 ret = false;15 throw new Exception("aaa");16 }finally{17
System.out.println("testEx2, finally; return value="+ret);18 }19 }
4.关于abrupt completion
前⾯提到了complete abruptly(暂且理解为“突然中⽌”或者“异常结束”吧),它主要包含了两种⼤的情形:
abrupt completion of expressions and statements,下⾯就分两种情况进⾏解释。