zoukankan      html  css  js  c++  java
  • 异常的一些基础知识

    人们利用面向对象的机制描述异常类。在这个模型下,人们一般将异常分为如下几个类型。

    ·异常 (Exception)
    这是所有异常的基类,任何一个异常需要从此异常类继承并构造实例。

    ·系统异常 (SystemException)
    系统异常往往用来描述操作系统发生的异常。例如文件不存在,内存不足等。

    ·应用程序异常 (ApplicationException)
    在 SystemException 的托管(Managed)下,为不同俄进程引发应用程序异常。

    ·非法操作异常 (InvalidOperationException)
    此异常隶属于单个应用程序,当在某一个应用程序中发生非法操作(例如:空指针、Access Validation 等),应用程序可以在它自己的堆中托管这些异常。

    ·其他异常
    诸如被零除、格式转换、正则表达式、对象引用等异常,这些异常通常由编写这些应用程序的主语言自动捕获和处理。

    一般来说,异常都是按照如下形式继承和传递的。

      Exception
        -- SystemException
          -- ApplicationException
            -- InvalidOperationException
            -- UnhandledException
            -- IOException
              -- FileNotFoundException

    可见, 异常的发生也是由先后顺序的。捕获异常也是一样。异常总是被更下一层的类捕获,例如,如果同时在代码中捕获了 IOException 和 FileNotFoundException,那么可能将执行代码路径 2。

    try{
        System.IO.File.CreateText("c:\a.txt");
    }
    catch(IOException ex1)
    {……}   //path1
    catch(FileNotFoundException ex2)
    {……}   //path2
    finally
    {
    System.GC.Release;
    }
    这就要求在书写代码时正确的捕获异常

    异常的结构。在.NET Framework中,所有的异常派生自System.Exception基类。其下有两个子类:SystemException和ApplicationException。自行编写异常类,不建议直接派生自Exception类,而是应该派生自ApplicationException。

    Message:描述当前异常的消息
    Source:发生当前异常的方法/应用程序
    Stacktrace:和当前异常相关的堆栈追踪

    如果可能,为每个可能的Exception定制解决方法。将Exception基类放在最后一个Catch子句是一个好办法。
    如果不想让程序被错误所终止,要在适当的地方使用try-catch。如果想让异常处理继承,需要在catch子句中写出一些具体的处理方法,空的catch段相当于给异常放行。暗示,在进行完catch子句后程序将继承执行。除非catch子句中有return、throw、System.Environment.Exit()等。

    必须正确排列捕获异常的catch子句,范围小的Exception放在前面。可使用finally段来确保收尾工作。

    你无法预防异常,但你能处理它们,以避免它们使你的程序崩溃.

    当你的程序遇到一个非正常情况,比如说内存不足,它就会引发(throw/raise)一个异常.此时,当前的过程调用将挂起,.net运行时(CLR)将从下至上搜索过程调用堆栈,以查找相应的异常处理程序.也就是说如果抛出异常的代码正处于某个Try块中,运行时将首先使用本地的Catch块(如果有)来处理异常(它将执行在该位置找到的Catch块代码),否则这个程序段将被终止并将异常的处理权交给其调用函数;如果没有函数处理此异常(即在整个调用堆栈中没能找到适当的catch块),最终运行时将会得到并处理它,并立刻将你的程序终止.
    即使代码抛出异常,并在catch块中添加了显式的return语句,finally块中的代码仍会被执行.Finally块中的代码将在异常处理代码之后,控制返回到调用过程之前执行.使用break,continue,return语句退出finally块都是非法的。 

    Exception类是基本的.NET错误类。会存在一些具体的异常类,但是它们并不都来自Exception类。例如,处理具体的SQL错误。SqlClient类包括了SqlException对象以处理专门针对它的错误。可以加入另一个Catch块来处理针对SQL的错误

    创建自己的异常:

    ㈠声明一个异常,格式如下:class ExceptionName:Exception{}

    ㈡引发自己的异常:throw(ExceptionName);

    要避免使用了try-catch但没有处理异常的情况,否则就相当于给异常放行(这种情况还不如根本就不去捕获它)。
     处理完异常,我们还应该注意在finally块中释放相关资源、还原相关设置信息等收尾工作。
    在做异常处理的时候,最好能在应用程序所有的入口处(事件处理函数,主函数,线程入口)使用try-catch。 但是不要在程序构造函数入口处添加try-catch,因为此处产生异常,它自己并没有能力来处理,因为它还没有构造完毕,只能再向外层抛出异常。

    对于一些简单的、能够提前避免的错误,我们还是应该在try块外面及早做出处理。
    if(z == 0)
    {
    Console.WriteLine("除数不能为零");
    // ...
    }
    try
    {
    int x = y/z;
    }
    catch
    {
    // ...
    }

    将全局异常处理函数的委托加入到 Application.ThreadException 中,实现全局异常处理,但它只能处理主线程中未捕获的异常。在多线程异常处理时,工作线程/辅线程中产生异常,可以把它转给主线程来完成异常处理。如果线程之间不通知,是无法直接捕捉异常的。若没有去处理工作线程/辅线程中产生的异常,该异常将会“消失”掉。

    为什么要把异常处理都交给主线程去做呢?举个例子:在WinForm里我们使用多线程来处理界面元素,一旦有异常发生就将异常消息显示出来。那么,是直接在异常发生后就MessageBox,还是将消息交给MainUI来统一显示?试想一下,程序要是复杂点或是有多个界面采用多线程来显示界面元素,那么采用前者,我们就算知道了异常的详细信息,但可能还是很难找到究竟是哪里出了问题。而通过MainUI来显示,情况就要好很多了,尤其是还设计到其他东西的时候(如:多语言环境)。当然,这个例子只是很小的一个方面。


  • 相关阅读:
    leetcode5 Longest Palindromic Substring
    leetcode17 Letter Combinations of a Phone Number
    leetcode13 Roman to Integer
    leetcode14 Longest Common Prefix
    leetcode20 Valid Parentheses
    leetcode392 Is Subsequence
    leetcode121 Best Time to Buy and Sell Stock
    leetcode198 House Robber
    leetcode746 Min Cost Climbing Stairs
    tomcat下使用druid配置jnid数据源
  • 原文地址:https://www.cnblogs.com/flashicp/p/680130.html
Copyright © 2011-2022 走看看