??xml version="1.0" encoding="utf-8" standalone="yes"?>日日噜噜噜噜夜夜爽亚洲精品,国产成人亚洲精品91专区手机,亚洲区日韩精品中文字幕http://www.tkk7.com/imdosop/category/35072.htmlq记得年时的梦?/description>zh-cnFri, 13 Jan 2012 20:26:26 GMTFri, 13 Jan 2012 20:26:26 GMT60Java异常处理之陋?/title><link>http://www.tkk7.com/imdosop/archive/2008/10/10/233545.html</link><dc:creator>東頭bing阉K</dc:creator><author>東頭bing阉K</author><pubDate>Fri, 10 Oct 2008 03:54:00 GMT</pubDate><guid>http://www.tkk7.com/imdosop/archive/2008/10/10/233545.html</guid><wfw:comment>http://www.tkk7.com/imdosop/comments/233545.html</wfw:comment><comments>http://www.tkk7.com/imdosop/archive/2008/10/10/233545.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/imdosop/comments/commentRss/233545.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/imdosop/services/trackbacks/233545.html</trackback:ping><description><![CDATA[你觉得自己是一个Java专家吗?是否肯定自己已经全面掌握?jin)Java的异常处理机Ӟ在下面这D代码中Q你能够q速找出异常处理的六个问题吗?  <br /> <br /> 1 OutputStreamWriter out = ...<br /> 2 java.sql.Connection conn = ...<br /> 3 try { // ?br /> 4    Statement stat = conn.createStatement();<br /> 5    ResultSet rs = stat.executeQuery(<br /> 6    "select uid, name from user");<br /> 7    while (rs.next())<br /> 8    {<br /> 9       out.println("IDQ? + rs.getString("uid") // ?br /> 10     "Q姓名:(x)" + rs.getString("name"));<br /> 11   }<br /> 12   conn.close(); // ?br /> 13   out.close();<br /> 14 }<br /> 15 catch(Exception ex) // ?br /> 16 {<br /> 17    ex.printStackTrace(); //_(d)?br /> 18 }<br /> <br />   作ؓ(f)一个JavaE序员,你至应该能够找Z个问题。但是,如果你不能找出全部六个问题,L(fng)l阅L文?nbsp; <br />   本文讨论的不是Java异常处理的一般性原则,因ؓ(f)q些原则已经被大多数人熟知。我们要做的是分析各U可UCؓ(f)“反例”Qanti-patternQ的q背优秀~码规范的常见坏?fn)惯Q帮助读者熟(zhn)这些典型的反面例子Q从而能够在实际工作中敏锐地察觉和避免这些问题?nbsp;<br />   反例之一Q丢弃异?<br />   代码Q?5?18行?nbsp; <br />   q段代码捕获?jin)异常却不作M处理Q可以算得上Java~程中的杀手。从问题出现的频J程度和害E度来看Q它也许可以和C/C++E序的一个恶名远播的问题相提q论——不(g)查缓冲区是否已满。如果你看到?jin)这U丢弃(而不是抛出)(j)异常的情况,可以癑ֈ之九(ji)十九(ji)地肯定代码存在问题(在极数情况下,q段代码有存在的理由Q但最好加上完整的注释Q以免引起别解)(j)?nbsp; <br />   q段代码的错误在于,异常Q几乎)(j)L意味着某些事情不对劲了(jin)Q或者说臛_发生?jin)某些不d的事情,我们不应该对E序发出的求救信号保持沉默和无动于衷。调用一下printStackTrace不?#8220;处理异常”。不错,调用printStackTrace对调试程序有帮助Q但E序调试阶段l束之后QprintStackTrace׃应再在异常处理模块中担负主要责Q?jin)?nbsp; <br />   丢弃异常的情形非常普遍。打开JDK的ThreadDeathcȝ文档Q可以看C面这D说明:(x)“特别圎ͼ虽然出现ThreadDeath是一U?#8216;正常的情?#8217;Q但ThreadDeathcLError而不是Exception的子c,因ؓ(f)许多应用?x)捕h有的Exception然后丢弃它不再理睬?#8221;q段话的意思是Q虽然ThreadDeath代表的是一U普通的问题Q但鉴于许多应用?x)试图捕h有异常然后不予以适当的处理,所以JDK把ThreadDeath定义成了(jin)Error的子c,因ؓ(f)ErrorcM表的是一般的应用不应该去捕获的严重问题。可见,丢弃异常q一坏习(fn)惯是如此常见Q它甚至已经影响C(jin)Java本n的设计?nbsp; <br />   那么Q应该怎样Ҏ(gu)呢?主要有四个选择Q?nbsp; <br />   1、处理异常。针对该异常采取一些行动,例如修正问题、提醒某个h或进行其他一些处理,要根据具体的情Ş定应该采取的动作。再ơ说明,调用printStackTrace不上已l?#8220;处理好了(jin)异常”?nbsp; <br />   2、重新抛出异常。处理异常的代码在分析异怹后,认ؓ(f)自己不能处理它,重新抛出异常也不׃ؓ(f)一U选择?br />   3、把该异常{换成另一U异常。大多数情况下,q是指把一个低U的异常转换成应用的异常(其含义更Ҏ(gu)被用户了(jin)解的异常Q?nbsp; <br />   4、不要捕获异常?nbsp; <br /> <br />   l论一Q既然捕获了(jin)异常Q就要对它进行适当的处理。不要捕获异怹后又把它丢弃Q不予理睬?nbsp; <br /> <br /> <br />   反例之二Q不指定具体的异?nbsp; <br />   代码Q?5行?nbsp; <br />   许多时候h们会(x)被这样一U?#8220;妙?#8221;x吸引Q用一个catch语句捕获所有的异常。最常见的情形就是用catch(Exception ex)语句。但实际上,在绝大多数情况下Q这U做法不值得提倡。ؓ(f)什么呢Q?nbsp; <br />   要理解其原因Q我们必d一下catch语句的用途。catch语句表示我们预期?x)出现某U异常,而且希望能够处理该异常。异常类的作用就是告诉Java~译器我们想要处理的是哪一U异常。由于绝大多数异帔R直接或间接从java.lang.ExceptionzQcatch(Exception ex)q当于说我们想要处理几乎所有的异常?nbsp; <br />   再来看看前面的代码例子。我们真正想要捕L(fng)异常是什么呢Q最明显的一个是SQLExceptionQ这是JDBC操作中常见的异常。另一个可能的异常是IOExceptionQ因为它要操作OutputStreamWriter。显?dng)在同一个catch块中处理q两U截然不同的异常是不合适的。如果用两个catch块分别捕获SQLException和IOExceptionp好多?jin)。这是_(d)catch语句应当量指定具体的异常类型,而不应该指定늛范围太广的ExceptioncR?nbsp; <br />   另一斚wQ除?jin)这两个特定的异常,q有其他许多异常也可能出现。例如,如果׃某种原因QexecuteQueryq回?jin)nullQ该怎么办?{案是让它们l箋抛出Q即不必捕获也不必处理。实际上Q我们不能也不应该去捕获可能出现的所有异常,E序的其他地方还有捕获异常的Z(x)——直x后由JVM处理?nbsp; <br />   l论二:(x)在catch语句中尽可能指定具体的异常类型,必要时用多个catch。不要试囑֤理所有可能出现的异常?nbsp; <br /> <br />   反例之三Q占用资源不释放  <br /> <br />   代码Q??14行?nbsp; <br />   异常改变?jin)程序正常的执行程。这个道理虽然简单,却常常被Z忽视。如果程序用C(jin)文g、Socket、JDBCq接之类的资源,即遇到?jin)异常,也要正确释放占用的资源。ؓ(f)此,Java提供?jin)一个简化这cL作的关键词finally?nbsp; <br />   finally是样好东西:(x)不管是否出现?jin)异常,Finally保证在try/catch/finally块结束之前,执行清理d的代码L有机?x)执行。遗憄是有些h却不?fn)惯使用finally?nbsp; <br />   当然Q编写finally块应当多加小?j),特别是要注意在finally块之内抛出的异常——这是执行清理Q务的最后机?x),量不要再有难以处理的错误?nbsp; <br /> <br />   l论三:(x)保证所有资源都被正释放。充分运用finally关键词?nbsp; <br /> <br />   反例之四Q不说明异常的详l信?nbsp; <br /> <br />   代码Q??18行?nbsp; <br /> <br />   仔细观察q段代码Q如果@环内部出C(jin)异常Q会(x)发生什么事情?我们可以得到_的信息判断@环内部出错的原因吗?不能。我们只能知道当前正在处理的cd生了(jin)某种错误Q但却不能获得Q何信息判断导致当前错误的原因?nbsp; <br />   printStackTrace的堆栈跟t功能显C出E序q行到当前类的执行流E,但只提供?jin)一些最基本的信息,未能说明实际D错误的原因,同时也不易解诅R?nbsp; <br />      因此Q在出现异常Ӟ最好能够提供一些文字信息,例如当前正在执行的类、方法和其他状态信息,包括以一U更适合阅读的方式整理和l织printStackTrace提供的信息?nbsp; <br /> <br />   l论四:(x)在异常处理模块中提供适量的错误原因信息,l织错误信息使其易于理解和阅诅R?nbsp; <br /> <br />   反例之五Q过于庞大的try?nbsp; <br /> <br />   代码Q??14行?nbsp; <br /> <br />   l常可以看到有h把大量的代码攑օ单个try块,实际上这不是好习(fn)惯。这U现象之所以常见,原因在于有些h囄事,不愿花时间分析一大块代码中哪几行代码?x)抛出异常、异常的具体cd是什么。把大量的语句装入单个巨大的try块就象是出门旅游时把所有日常用品塞入一个大子Q虽然东西是带上?jin),但要扑և来可不容易?nbsp; <br />   一些新手常常把大量的代码放入单个try块,然后再在catch语句中声明ExceptionQ而不是分d个可能出现异常的D落q分别捕获其异常。这U做法ؓ(f)分析E序抛出异常的原因带来了(jin)困难Q因Z大段代码中有太多的地方可能抛出Exception?nbsp; <br /> <br />   l论五:(x)量减小try块的体积?nbsp; <br /> <br />   反例之六Q输出数据不完整  <br /> <br />   代码Q??11行?nbsp; <br /> <br />   不完整的数据是JavaE序的隐形杀手。仔l观察这D代码,考虑一下如果@环的中间抛出?jin)异常,会(x)发生什么事情。@环的执行当然是要被打断的Q其ơ,catch块会(x)执行——就q些Q再也没有其他动作了(jin)。已l输出的数据怎么办?使用q些数据的h或设备将收到一份不完整的(因而也是错误的Q数据,却得不到M有关q䆾数据是否完整的提C。对于有些系l来_(d)数据不完整可能比pȝ停止q行带来更大的损失?nbsp; <br />   较ؓ(f)理想的处|办法是向输?gu)备写一些信息,声明数据的不完整性;另一U可能有效的办法是,先缓冲要输出的数据,准备好全部数据之后再一ơ性输出?nbsp; <br /> <br />   l论六:(x)全面考虑可能出现的异总?qing)这些异常对执行程的?jing)响?nbsp; <br /> <br /> <br />   改写后的代码  <br />   Ҏ(gu)上面的讨论,下面l出改写后的代码。也许有Z(x)说它E微有点啰嗦Q但是它有了(jin)比较完备的异常处理机制?nbsp; <br /> <pre> OutputStreamWriter out = ... java.sql.Connection conn = ... try {    Statement stat = conn.createStatement();    ResultSet rs = stat.executeQuery(    "select uid, name from user");    while (rs.next())    {       out.println("IDQ? + rs.getString("uid") +       "Q姓? " + rs.getString("name"));    } } catch(SQLException sqlex) {    out.println("警告Q数据不完整");    throw new ApplicationException(    "d数据时出现SQL错误", sqlex); } catch(IOException ioex) {    throw new ApplicationException(    "写入数据时出现IO错误", ioex); <br /> } finally {    if (conn != null) {       try {          conn.close();       }       catch(SQLException sqlex2)       {           System.err(this.getClass().getName() +           ".mymethod - 不能关闭数据库连? " +           sqlex2.toString());       }    } <br />    if (out != null) {       try {          out.close();       }       catch(IOException ioex2)       {          System.err(this.getClass().getName() +          ".mymethod - 不能关闭输出文g" +          ioex2.toString());       }    } } <br /> 本文的结Z是放之四L(fng)准的教条Q有时常识和l验才是最好的老师。如果你对自q做法没有癑ֈ之百的信?j),务必加上详细、全面的注释?<br /> 另一斚wQ不要笑话这些错误,不妨问问你自己是否真地彻底摆׃(jin)q些坏习(fn)惯。即使最有经验的E序员偶?dng)也会(x)误入歧途,原因很简单,因ؓ(f)它们确实实带来?#8220;方便”。所有这些反例都可以看作Java~程世界的恶,它们丽动hQ无孔不入,时刻诱惑着你。也许有Z(x)认ؓ(f)q些都属于鸡皮蒜毛的事Q不x齿,但请CQ勿以恶而ؓ(f)之,勿以善小而不为?/pre> <p><em style="font-size: 10pt; color: #c0c0c0">版权归原作者和各发布网站所有,此文章仅供学?fn)参考之?/em></p> <img src ="http://www.tkk7.com/imdosop/aggbug/233545.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/imdosop/" target="_blank">東頭bing阉K</a> 2008-10-10 11:54 <a href="http://www.tkk7.com/imdosop/archive/2008/10/10/233545.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java异常处理机制的深入理?lt;一>http://www.tkk7.com/imdosop/archive/2008/10/10/233526.html東頭bing阉K東頭bing阉KFri, 10 Oct 2008 02:49:00 GMThttp://www.tkk7.com/imdosop/archive/2008/10/10/233526.htmlhttp://www.tkk7.com/imdosop/comments/233526.htmlhttp://www.tkk7.com/imdosop/archive/2008/10/10/233526.html#Feedback0http://www.tkk7.com/imdosop/comments/commentRss/233526.htmlhttp://www.tkk7.com/imdosop/services/trackbacks/233526.html try…catch…finally恐怕是大家再熟(zhn)不q的语句?jin),而且感觉用v来也是很单,逻辑上似乎也是很Ҏ(gu)理解。不q,我亲自体验的“教训”告诉我,q个东西可不是想象中的那么简单、听话。不信?那你看看下面的代?span>Q?#8220;猜猜”它执行后的结果会(x)是什么?不要往后看{案、也不许执行代码看真正答案哦。如果你的答案是正确Q那么这文章你׃用浪Ҏ(gu)间看啦?/span>
package myExample.testException;
public class TestException {

    public TestException() {

    }

    boolean testEx() throws Exception{

        boolean ret = true;

        try{

            ret = testEx1();

        }catch (Exception e){

            System.out.println("testEx, catch exception");

            ret = false;

            throw e;

        }finally{

            System.out.println("testEx, finally; return value="+ret);

            return ret;

        }

    }

    boolean testEx1() throws Exception{

        boolean ret = true;

        try{

            ret = testEx2();

            if (!ret){

                return false;

            }            

System.out.println("testEx1, at the end of try");

            return ret;

        }catch (Exception e){

            System.out.println("testEx1, catch exception");

            ret = false;

            throw e;

        }

        finally{

            System.out.println("testEx1, finally; return value="+ret);

            return ret;

        }

    }

    boolean testEx2() throws Exception{

        boolean ret = true;

        try{

            int b=12;

            int c;

            for (int i=2;i>=-2;i--){

                c=b/i;

                System.out.println("i="+i);

            }

            return true;

        }catch (Exception e){

            System.out.println("testEx2, catch exception");

            ret = false;

            throw e;

        }

        finally{

            System.out.println("testEx2, finally; return value="+ret);

            return ret;

        }

    }

    public static void main(String[] args) {

        TestException testException1 = new TestException();

        try{

            testException1.testEx();

        }catch(Exception e){

            e.printStackTrace();

        }

    }

}





你的{案是什么?是下面的{案吗?

i=2

i=1

testEx2, catch exception

testEx2, finally; return value=false

testEx1, catch exception

testEx1, finally; return value=false

testEx, catch exception

testEx, finally; return value=false


如果你的{案真的如上面所_(d)那么你错啦。^_^Q那徏议你仔细看一看这文章或者拿上面的代码按各种不同的情况修攏V执行、测试,你会(x)发现有很多事情不是原来想象中的那么简单的?/span>

现在公布正确{案Q?br />
i=2

i=1

testEx2, catch exception

testEx2, finally; return value=false

testEx1, finally; return value=false

testEx, finally; return value=false



2 基础知识
2.1  相关概念
例外是在E序q行q程中发生的异常事gQ比如除0溢出、数l越界、文件找不到{,q些事g的发生将LE序的正常运行。ؓ(f)?jin)加强程序的鲁棒性,E序设计Ӟ必须考虑到可能发生的异常事gq做出相应的处理。C语言中,通过使用if语句来判断是否出C(jin)例外Q同Ӟ调用函数通过被调用函数的q回?a id="vad_7" onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,7,fxEvent);" style="font-size: 1em; cursor: pointer; color: #ff3366; border-bottom: #ff3366 1px dotted; text-decoration: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted'; kwmouseout(this,7)" target="_blank" name="7">感知在被调用函数中生的例外事gq进行处理。全E变量ErroNo常常用来反映一个异怺件的cd。但是,q种错误处理机制?x)导致不问题?/span>

Java通过面向对象?a id="vad_0" onmouseover="this.style.borderBottom='2px #FF3366 solid';var fxEvent=arguments[0];kwmouseover(this,0,fxEvent);" style="font-size: 1em; cursor: pointer; color: #ff3366; border-bottom: #ff3366 1px dotted; text-decoration: underline" onmouseout="this.style.borderBottom='1px #FF3366 dotted'; kwmouseout(this,0)" target="_blank" name="0">Ҏ(gu)来处理例外。在一个方法的q行q程中,如果发生?jin)例外,则这个方法生成代表该例外的一个对象,q把它交l运行时pȝQ运行时pȝL相应的代码来处理q一例外。我们把生成例外对象q把它提交给q行时系l的q程UCؓ(f)抛弃(throw)一个例外。运行时pȝ在方法的调用栈中查找Q从生成例外的方?/span>开?/a>q行回朔Q直到找到包含相应例外处理的Ҏ(gu)为止Q这一个过E称为捕?catch)一个例外?/span>

2.2  Throwablecd(qing)其子c?br />  用面向对象的Ҏ(gu)处理例外Q就必须建立cȝ层次。类 Throwable位于q一cdơ的最层Q只有它的后代才
可以做ؓ(f)一个例外被抛弃。图1表示?jin)例外处理的cdơ?/span>


从图中可以看出,cThrowable有两个直接子c:(x)Error和Exception。Errorcd象(如动态连接错误等Q,由Java虚拟机生成ƈ抛弃Q通常QJavaE序不对q类例外q行处理Q;Exceptioncd象是JavaE序处理或抛弃的对象。它有各U不同的子类分别对应于不同类型的例外。其中类RuntimeException代表q行时由Java虚拟机生成的例外Q如术q算例外ArithmeticException(由除0错等D)、数l越界例外ArrayIndexOutOfBoundsException{;其它则ؓ(f)非运行时例外Q如输入输出例外IOException{。Java~译器要求JavaE序必须捕获或声明所有的非运行时例外Q但对运行时例外可以不做处理?/span>

2.3  异常处理关键?br /> Java的异常处理是通过5个关键字来实现的QtryQcatchQthrowQthrowsQfinally。JB的在U帮助中对这几个关键字是q样解释的:(x)

Throws:  Lists the exceptions a method could throw.

Throw:   Transfers control of the method to the exception handler.

TryQ?nbsp;   Opening exception-handling statement.

CatchQ?nbsp; Captures the exception.

FinallyQ?Runs its code before terminating the program.

2.3.1          try语句 
try语句用大括号{}指定?jin)一D代码,该段代码可能?x)抛弃一个或多个例外?/span>

2.3.2          catch语句 
catch语句的参数类gҎ(gu)的声明,包括一个例外类型和一个例外对象。例外类型必Mؓ(f)Throwablecȝ子类Q它指明?jin)catch语句所处理的例外类型,例外对象则由q行时系l在try所指定的代码块中生成ƈ被捕P大括号中包含对象的处理,其中可以调用对象的方法?/span>

catch语句可以有多个,分别处理不同cȝ例外。Javaq行时系l从上到下分别对每个catch语句处理的例外类型进行检,直到扑ֈcd相匹配的catch语句为止。这里,cd匚w指catch所处理的例外类型与生成的例外对象的cd完全一致或者是它的父类Q因此,catch语句的排列顺序应该是从特D到一般?/span>



也可以用一个catch语句处理多个例外cdQ这时它的例外类型参数应该是q多个例外类型的父类Q程序设计中要根据具体的情况来选择catch语句的例外处理类型。 

2.3.3          finally语句 
try所限定的代码中Q当抛弃一个例外时Q其后的代码不会(x)被执行。通过finally语句可以指定一块代码。无论try所指定的程序块中抛弃或不抛弃例外,也无论catch语句的例外类型是否与所抛弃的例外的cd一_(d)finally所指定的代码都要被执行Q它提供?jin)统一的出口。通常在finally语句中可以进行资源的清除工作。如关闭打开的文件等?/span>

2.3.4          throws语句 
throwsL出现在一个函数头中,用来标明该成员函数可能抛出的各种异常。对大多数Exception子类来说QJava ~译器会(x)你声明在一个成员函C抛出的异常的cd。如果异常的cd是Error?RuntimeExceptionQ?或它们的子类Q这个规则不起作用, 因ؓ(f)q在E序的正帔R分中是不期待出现的?如果你想明确地抛Z个RuntimeExceptionQ你必须用throws语句来声明它的类型?br />
2.3.5          throw语句 
throwL出现在函C中,用来抛出一个异常。程序会(x)在throw语句后立即终止,它后面的语句执行不到Q然后在包含它的所有try块中Q可能在上层调用函数中)(j)从里向外L含有与其匚w的catch子句的try块?br />




3          关键字及(qing)其中语句程详解
3.1         try的嵌?br /> 你可以在一个成员函数调用的外面写一个try语句Q在q个成员函数内部Q写另一个try语句保护其他代码。每当遇C个try语句Q异常的框架放到堆栈上面,直到所有的try语句都完成。如果下一U的try语句没有Ҏ(gu)U异常进行处理,堆栈׃(x)展开Q直到遇到有处理q种异常的try语句。下面是一个try语句嵌套的例子?

class MultiNest {

    static void procedure() {

        try {

            int a = 0;

            int b = 42/a;

        } catch(java.lang.ArithmeticException e) {

            System.out.println("in procedure, catch ArithmeticException: " + e);

        }

    }





    public static void main(String args[]) {

        try {

            procedure();

        } catch(java.lang. Exception e) {

            System.out.println("in main, catch Exception: " + e);

        }

    }

}





q个例子执行的结果ؓ(f)Q?br />
in procedure, catch ArithmeticException: java.lang.ArithmeticException: / by zero



成员函数procedure里有自己的try/catch控制Q所以main不用d?ArrayIndexOutOfBoundsExceptionQ当然如果如同最开始我们做试的例子一P在procedure中catch到异常时使用throw e;语句异常抛出,那么main当然q是能够捕捉q处理这个procedure抛出来的异常。例如在procedure函数的catch中的System.out语句后面增加throw e;语句之后Q执行结果就变ؓ(f)Q?/span>

in procedure, catch ArithmeticException: java.lang.ArithmeticException: / by zero



in main, catch Exception: java.lang.ArithmeticException: / by zero




3.2         try-catchE序块的执行程以及(qing)执行l果
相对于try-catch-finallyE序块而言Qtry-catch的执行流E以?qing)执行结果还是比较简单的?br />
首先执行的是try语句块中的语句,q时可能?x)有以下三种情况Q?br />
1Q?nbsp;             如果try块中所有语句正常执行完毕,那么׃?x)有其他?#8220;动做”被执行,整个try-catchE序块正常完成?br />
2Q?nbsp;             如果try语句块在执行q程中碰到异常VQ这时又分ؓ(f)两种情况q行处理Q?br />
&sup2;        如果异常V能够被与try相应的catch块catch刎ͼ那么W一个catch到这个异常的catch块(也是try最q的一个与异常V匚w的catch块)(j)被执行Q如果catch块执行正常,那么try-catchE序块的l果是“正常完成”Q如果该catch块由于原因RH然中止Q那么try-catchE序块的l果是“׃原因RH然中止Qcompletes abruptlyQ?#8221;?br />
&sup2;        如果异常V没有catch块与之匹配,那么q个try-catchE序块的l果是“׃抛出异常V而突然中止(completes abruptlyQ?#8221;?br />
3Q?nbsp;              如果try׃其他原因RH然中止Qcompletes abruptlyQ,那么q个try-catchE序块的l果是“׃原因RH然中止Qcompletes abruptlyQ?#8221;?br />
3.3         try-catch-finallyE序块的执行程以及(qing)执行l果
try-catch-finallyE序块的执行程以及(qing)执行l果比较复杂?br />
首先执行的是try语句块中的语句,q时可能?x)有以下三种情况Q?br />
1Q?nbsp;             如果try块中所有语句正常执行完毕,那么finally块的居于׃(x)被执行,q时分ؓ(f)以下两种情况Q?br />
&sup2;        如果finally块执行顺利,那么整个try-catch-finallyE序块正常完成?br />
&sup2;        如果finally块由于原因RH然中止Q那么try-catch-finallyE序块的l局?#8220;׃原因RH然中止Qcompletes abruptlyQ?#8221;

2Q?nbsp;             如果try语句块在执行q程中碰到异常VQ这时又分ؓ(f)两种情况q行处理Q?br />
&sup2;        如果异常V能够被与try相应的catch块catch刎ͼ那么W一个catch到这个异常的catch块(也是try最q的一个与异常V匚w的catch块)(j)被执行Q这时就?x)有两种执行l果Q?br />
&sup2;        如果catch块执行正常,那么finally块将?x)被执行Q这时分ZU情况:(x)

&sup2;        如果finally块执行顺利,那么整个try-catch-finallyE序块正常完成?br />
&sup2;        如果finally块由于原因RH然中止Q那么try-catch-finallyE序块的l局?#8220;׃原因RH然中止Qcompletes abruptlyQ?#8221;

&sup2;        如果catch块由于原因RH然中止Q那么finally模块被执行Q分ZU情况:(x)

&sup2;        如果如果finally块执行顺利,那么整个try-catch-finallyE序块的l局?#8220;׃原因RH然中止Qcompletes abruptlyQ?#8221;?br />
&sup2;        如果finally块由于原因SH然中止Q那么整个try-catch-finallyE序块的l局?#8220;׃原因SH然中止Qcompletes abruptlyQ?#8221;Q原因R被抛弃?br />
Q注意,q里正好和我们的例子相W合Q虽然我们在testEx2中用throw e抛出?jin)异常,但是׃testEx2中有finally块,而finally块的执行l果是complete abruptly的(别小看这个用得最多的returnQ它也是一U导致complete abruptly的原因之一啊——后文中有关于导致complete abruptly的原因分析)(j)Q所以整个try-catch-finallyE序块的l果?#8220;complete abruptly”Q所以在testEx1中调用testEx2时是捕捉不到testEx1中抛出的那个异常的,而只能将finally中的returnl果获取到?br />
如果在你的代码中期望通过捕捉被调用的下函数的异常来l定q回|那么一定要注意你所调用的下U函C的finally语句Q它有可能会(x)使你throw出来的异常ƈ不能真正被上U调用函数可见的。当然这U情冉|可以避免的,以testEx2ZQ如果你一定要使用finally而且又要catch中throw的e在testEx1中被捕获刎ͼ那么你去掉testEx2中的finally中的return可以了(jin)?/span>



q个事情已经在OMC2.0的MIB中出现过啦:(x)服务器的异常不能完全被反馈到客户端。)(j)

&sup2;        如果异常V没有catch块与之匹配,那么finally模块被执行Q分ZU情况:(x)

&sup2;        如果finally块执行顺利,那么整个try-catch-finallyE序块的l局是“׃抛出异常V而突然中止(completes abruptlyQ?#8221;?br />
&sup2;        如果finally块由于原因SH然中止Q那么整个try-catch-finallyE序块的l局?#8220;׃原因SH然中止Qcompletes abruptlyQ?#8221;Q异常V被抛弃?br />
3Q?nbsp;             如果try׃其他原因RH然中止Qcompletes abruptlyQ,那么finally块被执行Q分ZU情况:(x)

&sup2;        如果finally块执行顺利,那么整个try-catch-finallyE序块的l局?#8220;׃原因RH然中止Qcompletes abruptlyQ?#8221;?br />
&sup2;        如果finally块由于原因SH然中止Q那么整个try-catch-finallyE序块的l局?#8220;׃原因SH然中止Qcompletes abruptlyQ?#8221;Q原因R被抛弃?br />
3.4         try-catch-finallyE序块中的return
从上面的try-catch-finallyE序块的执行程以及(qing)执行l果一节中可以看出无论try或catch中发生了(jin)什么情况,finally都是?x)被执行的,那么写在try或者catch中的return语句也就不会(x)真正的从该函C跛_?jin),它的作用在这U情况下变成了(jin)控制权Q语句流E)(j)转到finally块中Q这U情况下一定要注意q回值的处理?/span>

例如Q在try或者catch中return false?jin),而在finally中又return trueQ那么这U情况下不要期待你的try或者catch中的return false的返回值false被上U调用函数获取到Q上U调用函数能够获取到的只是finally中的q回|因ؓ(f)try或者catch中的return语句只是转移控制权的作用?br />
3.5         如何抛出异常
如果你知道你写的某个函数有可能抛出异常,而你又不惛_q个函数中对异常q行处理Q只是想把它抛出去让调用q个函数的上U调用函数进行处理,那么有两U方式可供选择Q?br />
W一U方式:(x)直接在函数头中throws SomeExceptionQ函C中不需要try/catch。比如将最开始的例子中的testEx2改ؓ(f)下面的方式,那么testEx1p捕捉到testEx2抛出的异怺(jin)?/span>

    boolean testEx2() throws Exception{

        boolean ret = true;

        int b=12;

        int c;

        for (int i=2;i>=-2;i--){

            c=b/i;

            System.out.println("i="+i);

        }

        return true;    

}





W二U方式:(x)使用try/catchQ在catch中进行一定的处理之后Q如果有必要的话Q抛出某U异常。例如上面的testEx2改ؓ(f)下面的方式,testEx1也能捕获到它抛出的异常:(x)

    boolean testEx2() throws Exception{

        boolean ret = true;

        try{

            int b=12;

            int c;

            for (int i=2;i>=-2;i--){

                c=b/i;

                System.out.println("i="+i);

            }

            return true;

        }catch (Exception e){

            System.out.println("testEx2, catch exception");

            Throw e;

        }

    }





W三U方法:(x)使用try/catch/finallyQ在catch中进行一定的处理之后Q如果有必要的话Q抛出某U异常。例如上面的testEx2改ؓ(f)下面的方式,testEx1也能捕获到它抛出的异常:(x)

    boolean testEx2() throws Exception{

        boolean ret = true;

        try{

            int b=12;

            int c;

            for (int i=2;i>=-2;i--){

                c=b/i;

                System.out.println("i="+i);

                throw new Exception("aaa");

            }

            return true;

        }catch (java.lang.ArithmeticException e){

            System.out.println("testEx2, catch exception");

            ret = false;

            throw new Exception("aaa");

        }finally{

            System.out.println("testEx2, finally; return value="+ret);

        }

    }

4          关于abrupt completion
前面提到?jin)complete abruptlyQ暂且理解ؓ(f)“H然中止”或?#8220;异常l束”吧)(j)Q它主要包含?jin)两U大的情形:(x)abrupt completion of expressions and statementsQ下面就分两U情况进行解释?br />
4.1         Normal and Abrupt Completion of Evaluation
每一个表辑ּQexpressionQ都有一U得其包含的计得以一步步q行的正常模式,如果每一步计都被执行且没有异常抛出Q那么就U这个表辑ּ“正常l束Qcomplete normallyQ?#8221;Q如果这个表辑ּ的计抛Z(jin)异常Q就UCؓ(f)“异常l束Qcomplete abruptlyQ?#8221;。异常结束通常有一个相兌的原因(associated reasonQ,通常也就是抛Z个异常V?br />
与表辑ּ、操作符相关的运行期异常有:(x)

&sup2;        A class instance creation expression, array creation expression , or string concatenation operatior expression throws an OutOfMemoryError if there is insufficient memory available.

&sup2;        An array creation expression throws a NegativeArraySizeException if the value of any dimension expression is less than zero.

&sup2;        A field access throws a NullPointerException if the value of the object reference  expression is null.

&sup2;        A method invocation expression that invokes an instance method throws a NullPointerException if the target reference is null.

&sup2;        An array access throws a NullPointerException if the value of the array reference  expression is null.

&sup2;        An array access throws an ArrayIndexOutOfBoundsException if the value of the array index expression is negative or greater than or equal to the length of the array.

&sup2;        A cast throws a ClassCastException if a cast is found to be impermissible at run time.

&sup2;        An integer division or integer remainder operator throws an ArithmeticException if the value of the right-hand operand expression is zero.

&sup2;        An assignment to an array component of reference type throws an ArrayStoreException when the value to be assigned is not compatible with the component type of the array.

4.2         Normal and Abrupt Completion of Statements
正常情况我们׃多说?jin),在这里主要是列出了(jin)abrupt completion的几U情况:(x)

&sup2;        break, continue, and return 语句导致控制权的{换,从而得statements不能正常地、完整地执行?

&sup2;        某些表达式的计算也可能从java虚拟机抛出异常,q些表达式在上一节中已lȝq了(jin)Q一个显式的的throw语句也将D异常的抛出。抛出异怹是导致控制权的{换的原因Q或者说是阻止statement正常l束的原因)(j)?





如果上述事g发生?jin),那么q些statement有可能使得其正常情况下应该都执行的语句不能完全被执行到Q那么这些statement也就是被UCؓ(f)是complete abruptly.

Dabrupt completion的几U原因:(x)

&sup2;        A break with no label

&sup2;        A break with a given label

&sup2;        A continue with no label

&sup2;        A continue with a given label

&sup2;        A return with no value

&sup2;        A return with a given value A

&sup2;        throw with a given value, including exceptions thrown by the Java virtual machine

5          关于我们的编E的一点徏?br /> 弄清楚try-catch-finally的执行情况后我们才能正确使用它?br />
如果我们使用的是try-catch-finally语句块,而我们又需要保证有异常时能够抛出异常,那么在finally语句中就不要使用return语句?jin)(finally语句块的最重要的作用应该是释放甌的资源)(j)Q因为finally中的return语句?x)导致我们的throw e被抛弃,在这个try-catch-finally的外面将只能看到finally中的q回|除非在finally中抛出异常)(j)。(我们需要记住:(x)不仅throw语句是abrupt completion 的原因,return、break、continue{这些看h很正常的语句也是Dabrupt completion的原因。)(j)

版权归原作者和各发布网站所有,此文章仅供学?fn)参考之?/em>

東頭bing阉K 2008-10-10 10:49 发表评论
]]>
Java异常处理学习(fn)W记http://www.tkk7.com/imdosop/archive/2008/10/09/233304.html東頭bing阉K東頭bing阉KThu, 09 Oct 2008 03:10:00 GMThttp://www.tkk7.com/imdosop/archive/2008/10/09/233304.htmlhttp://www.tkk7.com/imdosop/comments/233304.htmlhttp://www.tkk7.com/imdosop/archive/2008/10/09/233304.html#Feedback0http://www.tkk7.com/imdosop/comments/commentRss/233304.htmlhttp://www.tkk7.com/imdosop/services/trackbacks/233304.html一、异常的概念和Java异常体系l构
Java把异常当作对象来处理Qƈ定义一个基cjava.lang.Throwable作ؓ(f)所有异常的类。在Java API中已l定义了(jin)许多异常c,q些异常cdZ大类Q错误Error和异常Exception?br /> ThorwablecL有异常和错误的超c,有两个子cError和ExceptionQ分别表C错误和异常。其中异常类Exception又分行时异常(RuntimeException)和非q行时异常,也称之ؓ(f)不检查异常(Unchecked ExceptionQ和(g)查异常(Checked ExceptionQ?br /> Error是程序无法处理的错误Q比如OutOfMemoryError、ThreadDeath{。这些异常发生时QJava虚拟机(JVMQ一般会(x)选择U程l止?
Exception是程序本w可以处理的异常Q这U异常分两大c运行时异常和非q行时异常。程序中应当可能去处理q些异常?br /> q行时异帔R是RuntimeExceptioncd(qing)其子cd常,如NullPointerException、IndexOutOfBoundsException{,q些异常是不(g)查异常,E序中可以选择捕获处理Q也可以不处理。这些异怸般是q序逻辑错误引v的,E序应该从逻辑角度可能避免这cd常的发生?br /> 非运行时异常是RuntimeException以外的异常,cd上都属于Exceptioncd(qing)其子cR从E序语法角度讲是必须q行处理的异常,如果不处理,E序׃能编译通过。如IOException、SQLException{以?qing)用戯定义的Exception异常Q一般情况下不自定义(g)查异常?br />
二、异常的捕获和处?br /> Java异常的捕获和处理是一个不Ҏ(gu)把握的事情,如果处理不当Q不但会(x)让程序代码的可读性大大降低,而且Dpȝ性能低下Q甚臛_发一些难以发现的错误?br /> Java异常处理涉及(qing)C个关键字Q分别是Qtry、catch、finally、throw、throws?br />

try、catch、finally三个语句块应注意的问?br /> 1>try、catch、finally三个语句块均不能单独使用Q三者可以组?try...catch...finally、try...catch、try...finally三种l构Qcatch语句可以有一个或多个Qfinally语句最多一个?br /> 2>try、catch、finally三个代码块中变量的作用域Z码块内部Q分别独立而不能相互访问。如果要在三个块中都可以讉KQ则需要将变量定义到这些块的外面?br /> 3>多个catch块时候,只会(x)匚w其中一个异常类q执行catch块代码,而不?x)再执行别的catch块,q且匚wcatch语句的顺序是׃C?br /> throw、throws关键?br /> throw关键字是用于Ҏ(gu)体内部,用来抛出一个Throwablecd的异常。如果抛Z(jin)(g)查异常,则还应该在方法头部声明方法可能抛出的异常cd。该Ҏ(gu)的调用者也必须(g)查处理抛出的异常。如果所有方法都层层上抛获取的异常,最lJVM?x)进行处理,处理也很单,是打印异常消息和堆栈信息。如果抛出的是Error或RuntimeExceptionQ则该方法的调用者可选择处理该异常?br /> throws关键字用于方法体外部的方法声明部分,用来声明Ҏ(gu)可能?x)抛出某些异常。仅当抛Z(jin)(g)查异常,该方法的调用者才必须处理或者重新抛?gu)异常。当Ҏ(gu)的调用者无力处理该异常的时候,应该l箋抛出Q而不是囫囵吞枣一般在catch块中打印一下堆栈信息做个勉强处理?br />
三?nbsp;异常处理的一般原?br /> 1>能处理就早处理,抛出不去q不能处理的想法消化掉或者{换ؓ(f)RuntimeException处理。因为对于一个应用系l来_(d)抛出大量异常是有问题的,应该从程序开发角度尽可能的控制异常发生的可能?br /> 2>对于(g)查异常,如果不能行之有效的处理,q不如{换ؓ(f)RuntimeException抛出。这样也让上层的代码有选择的余地――可处理也可不处理?br /> 3>对于一个应用系l来_(d)应该有自q一套异常处理框Ӟq样当异常发生时Q也能得到统一的处理风|优雅的异常信息反馈l用戗?/p>

東頭bing阉K 2008-10-09 11:10 发表评论
]]>
վ֩ģ壺 ƴƬ30ӹƷ| Ӱ| ޹AV| ޹Ʒþþò | ձվ| վ߹ۿ| ĻƷѾþӰԺ| Ƭһ| AVƷɫ| ߹ۿ| 츾avҹ벻| ĻӰ߾Ʒ| ߹ۿһƬ| www.ɫվ| | avƬ| | ɫվWWWþþž| Ƶһ| A벥ëƬһ| ߹ۿ| 91ƷѾþù鶹| ëƬվ| ޾Ʒר| ޹ɫƵ| ˳߹ۿվ| 99Ʒѹۿ| ר| 鶹AV뾫Ʒþ| ޴߶רһ| 91Ƶ| Ƶһ| ɫĻAV| л| 99re6ƵƷ| Ѹ弤Ƶ| žžۺAVһ| ޹Ʒվ߲| ձ߿Ƭ| ߹ۿĻɫַ| ޹Ʒþ˰|