zoukankan      html  css  js  c++  java
  • 读书笔记:《Java2 教程》(八)

    Java异常处理:

     

    什么是异常:

    异常可以看做是运行时的错误,不正常的操作产生的结果等,可能来源于I/O错误,设计逻辑的错误等。

    异常处理就是一种用于方便捕捉并进入适当处理过程的手段,可以方便我们的程序设计。

    方法:

    try{} catch{} finally{} 组合来捕获并处理异常。

     

    其中,try{}用于定义可能产生异常的代码段,catch{}部分是用来处理异常的,而finally{}部分则做一些清理工作。其处理的逻辑是:

    1 try中语句在执行中如果没有发生异常,则转到 后继续运行

    2 try段中一旦某一条语句发生了异常,则在try段其余的语句不会被继续执行,而是立即转到catch部分进行异常处理。

    3 finally段是一个特殊的地方,其中的代码一定会被执行:在没有发生异常的情况下,在try块之后执行;发生异常后,则在符合条件的catch语句段后执行!切记!

    4 finally段一般用于完成关闭文件,释放网络套接字,或者其它清理工作。

    5 try{} catch{} finally{} 组合中,以下情况都是真确的:

      try{} catch{} finally{}       完全版本

    try{} catch{}                 没有finally{}

      try{} finally{}               没有catch{}

    但是,如果没有catch{} finally{} ,而只有try{},这时Java语法所不允许的。

    注意:

    try catch 代码段是不可分割的;

    对一个catch 代码段,可以存在多个catch 部分,分别用来捕获不同类型的异常,这些catch部分也不能分开;

     

    接下来,我们来思考一个问题:当我们采用try{} finally{}组合时,程序如何来处理异常呢?是的,我们没有提供catch{}代码段,那么在异常发生以后,我们没有处理,这个异常怎么样了?答案是,这个异常被转给了该方法的调用者。应该了解的一个常识是,在执行过程方法调用的时候,计算机实际上会做一个保护调用环境,并将其压栈的工作,然后才转到被调用的过程和方法的入口开始执行;执行完毕,将栈中保存的环境进行恢复,回到调用者调用该方法的语句,继续执行。为什么要说这个呢,因为我们的问题和这个背景知识有密切的关系:异常被转移了。这个机制被成为:异常传递机制。如果调用者也不处理,那么异常就继续沿调用顺序继续被传递,直至到达main()函数,如果main()还是不处理,那只能由JVM站出来了,最后的结果就是屏幕上出现一些错误信息:告诉用户,应用发生了异常,是从哪里开始发生的,等等……,我现在没有办法继续工作了。(谁让你们都不处理的?)

     

    Java的异常捕获顺序

    JavaException 有很多种类,在Java1.4api document中,列出的就有:

    Direct Known Subclasses:

    AclNotFoundException, ActivationException, AlreadyBoundException, ApplicationException, AWTException, BackingStoreException, BadLocationException, CertificateException, ClassNotFoundException, CloneNotSupportedException, DataFormatException, DestroyFailedException, ExpandVetoException, FontFormatException, GeneralSecurityException, GSSException, IllegalAccessException, InstantiationException, InterruptedException, IntrospectionException, InvalidMidiDataException, InvalidPreferencesFormatException, InvocationTargetException, IOException, LastOwnerException, LineUnavailableException, MidiUnavailableException, MimeTypeParseException, NamingException, NoninvertibleTransformException, NoSuchFieldException, NoSuchMethodException, NotBoundException, NotOwnerException, ParseException, ParserConfigurationException, PrinterException, PrintException, PrivilegedActionException, PropertyVetoException, RefreshFailedException, RemarshalException, RuntimeException, SAXException, ServerNotActiveException, SQLException, TooManyListenersException, TransformerException, UnsupportedAudioFileException, UnsupportedCallbackException, UnsupportedFlavorException, UnsupportedLookAndFeelException, URISyntaxException, UserException, XAException

     

    很多吧。在我们的程序中,有两个不可能是我们要知道的:

    我们的程序不可能处理所有的异常;

    我们的程序也不可能产生所有的异常;

     

    我们只关心也只可能关心其中一部分我们感兴趣的种类。

    前面我们也提到了,一个try{} 代码段可以有多个catch{},那么我们怎么安排这多个catch{}呢?原则:先特殊,再一般。就是说,先处理子类异常,再处理父类异常。可能不太好理解,举个例子:

    public class  ReadFile

        public static void main()

       

            try

    {

        //some statement which concerning about reading files.

    }

    catch(FileNotFoundException e)

    {

        System.err.println(“File not fond.”);

        System.err.println(e.getMessage());

        e.printStackTrace();

    }

    catch(IOException e)

    {

        System.err.println(“I/O error.”);

        System.err.println(e.getMessage());

        e.printStackTrace();

    }

     

    为什么把处理FileNotFoundException的部分放在IOException 前面?还记得前面说的原则吗?在有多个catch段的情况下,先子类后父类。从api document中我们可以找到这样的描述:

    Class FileNotFoundException

    java.lang.Object

      java.lang.Throwable

          java.lang.Exception

              java.io.IOException

                  java.io.FileNotFoundException

     

    看到了吗?FileNotFoundException是从IOException继承来的。这下明白了吧。

    如果我们把这个顺序反过来会怎么样呢?你可以自己试试看。

    结果是什么?Java编译器报错了:……Exception  has already been caught.

     

    抛出和处理的博弈:

    我们的程序中,我们出了要处理异常,也会抛出异常。Java规定,如果我们自己的方法需要抛出异常,我们就有责任来告诉编译器,这就是抛出异常声明,除非,要抛出的异常是RunimeException的子类。

    对这个问题的详细解释是:

    1 Java中的异常分为两种:一种是检查异常,一种是非检查异常。非检查异常指RuntimeException 或者Error 及它们的子类。

    2 检查异常需要被捕获和处理;非检查异常则不必。

    3 Java要求每一个用Java语言来实现的方法,或者以catch{}代码段来捕获检查异常,或者在方法的声明语句中告诉编译器,自己要传递检查异常(把异常抛出),其格式是

        public MethodName() throw **Exception

    {

        //statements

    }

    其中 **的意思是指定某一类的异常。

    4 还有一种特殊情况,尽管我们提供了catch{}代码段来处理异常,但处理的方式是把异常继续抛出,那么我们就必须同时通知编译器,自己可能要把异常抛出。这是一个极端的例子。

     

    总结下来,就是说,对于检查异常,我们要不自己处理,要不就声明自己可能抛出异常,否则,编译报错。是不是象捕获处理和抛出的博弈呢?

     

    反思Java编译器的抱怨

    Java编译器为设么会这么设计?这和Java的设计逻辑有关。根据它的设计思想,使程序正常工作使开发人员的责任。为了达到这一个目的,Java某种程度上强制用户去关心错误的处理(捕获,处理异常),这样,异常处理的部分就成为程序的一个组成部分了,这也从很大程度上帮助增强了Java程序的稳定性和健壮性。

     

    但是,我们看到这样的程序了吗:

            try

    {

        //some statement

    }

    catch(Exception e)  {}

    什么感想?人类真“伟大”,这真是“上有政策,下有对策” Java语言中的典型体现啊!不错,编译通过了,可这和编译器被设计有这样要求的初衷却相去遥远了。我们聪明的欺骗了可怜的智能有限的编译器,我们自己呢?除了一时的方便之外,我们得到什么了呢?

     

    说明:从这部分开始,我同时参考了另外一本Java 教材:《Java2学习指南》,以丰富笔记的内容,并通过对比的方式,从不同的角度来更好的理解知识点。

    我个人的感觉,这是一本很不错的教程,内容组织合理全面,基本覆盖到了java 语言的各主要内容,翻译也很好,语句通顺,表意明了。推荐各位有空阅读。

    书籍信息:

    Java2学习指南 (美)贝茨等著 袁鹏飞等译 人民邮电出版社 2004.01出版 ISBN 7-115-11803-5

    English Name: Sun Certified Programmer Developer for Java2   Bates. B.

     

     

     

    相关文章:
    读书笔记:《Java2 教程》(一)

    读书笔记:《Java2 教程》(

    读书笔记:《Java2 教程》(三)

    读书笔记:《Java2 教程》(四)

    读书笔记:《Java2 教程》(五)

    读书笔记:《Java2 教程》(六)

    读书笔记:《Java2 教程》(七)

     

  • 相关阅读:
    关于时间
    ELK日志平台
    Java web项目
    阳光下的挣扎
    Windows Server 2008 R2无法连接无线网络的解决方法
    像进度条的网页加载Loading JS代码
    JAVASCRIPT网页上下切换的打开特效
    霓虹灯文字代码 JS网页特效
    Js代码动态移动层-拖动浮层并关闭
    JS网页特效:星空飞入效果
  • 原文地址:https://www.cnblogs.com/A1240/p/170399.html
Copyright © 2011-2022 走看看