exception_exceptions - CSDN
  • 1.异常的体系 (1)异常:所谓异常指的就是程序在 运行时 出现错误时通知调用者的一种机制. (2)基本语法 try{ 有可能出现异常的语句 ; }[catch (异常类型 异常对象) { } ......[finally { 异常的出口 ...

    1.异常的体系

    (1)异常:所谓异常指的就是程序在 运行时 出现错误时通知调用者的一种机制.
    (2)基本语法

    try{
    有可能出现异常的语句 ;
    }[catch (异常类型 异常对象) {
    } ... ]
    [finally {
    异常的出口
    }]
    

    a).try 代码块中放的是可能出现异常的代码.
    b).catch 代码块中放的是出现异常后的处理行为.
    c).finally 代码块中的代码用于处理善后工作, 会在最后执行.
    其中 catch 和 finally 都可以根据情况选择加或者不加
    d)如果加了finally,无论是否存在异常, finally 中的代码一定都会执行到.

    (3)异常体系
    在这里插入图片描述
    a) Error 指的是 Java 运行时内部错误和资源耗尽错误. 应用程序不抛出此类异常;
    b)Exception 是我们所使用的异常类的父类.其中 Exception 有一个子类称为 RuntimeException(运行时异常);
    c)Java语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为 非受查异常, 所有的其他异常称为受查异常;
    d)受查异常的处理式
    A:使用 try catch 包裹起来;
    B:在方法上加上异常说明, 相当于将处理动作交给上级调用者;

    2.处理异常的流程

    (1)程序先执行 try 中的代码.
    (2)如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.
    (3)如果找到匹配的异常类型, 就会执行 catch 中的代码.
    (4)如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.
    (5)无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).
    (6)如果上层调用者也没有处理的了异常, 就继续向上传递.
    (7)一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止

    3.异常当中的问题

    (1)throws 关键字, 把可能抛出的异常显式的标注在方法定义的位置. 从而提醒调用者要注意捕获这些异常.
    (2)finally 执行的时机是在方法返回之前(try 或者 catch 中如果有 return 会在这个 return 之前执行 finally). 但是如果finally 中也存在 return 语句, 那么就会执行 finally 中的 return, 从而不会执行到 try 中原有的 return

    展开全文
  • 常见异常类型; 算数异常类:ArithmeticExecption 空指针异常类型:NullPointerException 类型强制转换类型:ClassCastException ...数组负下标异常:NegativeArrayException ...数组下标越界异常:...

    常见异常类型;


    算数异常类:ArithmeticExecption


    空指针异常类型:NullPointerException


    类型强制转换类型:ClassCastException


    数组负下标异常:NegativeArrayException


    数组下标越界异常:ArrayIndexOutOfBoundsException


    违背安全原则异常:SecturityException


    文件已结束异常:EOFException


    文件未找到异常:FileNotFoundException


    字符串转换为数字异常:NumberFormatException


    操作数据库异常:SQLException


    输入输出异常:IOException


    方法未找到异常:NoSuchMethodException


    下标越界异常:IndexOutOfBoundsExecption


    系统异常:SystemException


    创建一个大小为负数的数组错误异常:NegativeArraySizeException


    数据格式异常:NumberFormatException


    安全异常:SecurityException


    不支持的操作异常:UnsupportedOperationException


    更多的就靠自己积累了...




    展开全文
  • C++/C++11中std::exception的使用

    std::exception:标准异常类的基类,其类的声明在头文件<exception>中。所有标准库的异常类均继承于此类,因此通过引用类型可以捕获所有标准异常。

    std::exception类定义了无参构造函数、拷贝构造函数、拷贝赋值运算符、一个虚析构函数和一个名为what的无参虚成员。其中what函数返回一个const char*,该指针指向一个以null结尾的字符数组,并且确保不会抛出任何异常,该字符串的目的是提供关于异常的一些文本信息。除析构函数外,其它函数均通过关键字noexcept说明此函数不会抛出异常。

    std::exception is the class whose only purpose is to serve as the base class in the exception hierarchy. It has no other uses. In other words, conceptually it is an abstract class (even though it is not defined as abstract class in C++ meaning of the term).

    以下内容摘自:《C++Primer(Fifth Edition)》

    异常是指在程序运行时发生的反常行为,这些行为超出了函数正常功能的范围。典型的异常包括失去数据库连接以及遇到意外输入等。当程序的某部分检测到一个它无法处理的问题时,需要用到异常处理。此时,检测出问题的部分应该发出某种信号以表明程序遇到了故障,无法继续下去了,而且信号的发出方无须知道故障将在何处得到解决。一旦发出异常信号,检测出问题的部分也就完成了任务。

    异常提供了一种转移程序控制权的方式。C++异常处理涉及到三个关键字:try、catch、throw。关于这三个关键字的简单使用可以参考: http://blog.csdn.net/fengbingchun/article/details/65939258 

    异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持。在C++语言中,异常处理包括:

     (1)、throw表达式(throw expression):异常检测部分使用throw表达式来表示它遇到了无法处理的问题。throw引发(raise)异常。throw表达式包含关键字throw和紧随其后的一个表达式,其中表达式的类型就是抛出的异常类型。throw表达式后面通常紧跟一个分号,从而构成一条表达式语句。抛出异常将终止当前的函数,并把控制权转移给能处理该异常的代码

    (2)、try语句块(try block):异常处理部分使用try语句块处理异常。try语句块以关键字try开始,并以一个或多个catch子句(catch clause)结束。try语句块中代码抛出的异常通常会被某个catch子句处理。因为catch子句处理异常,所以它们也被称作异常处理代码(exception handler)。catch子句包括三部分:关键字catch、括号内一个(可能未命名的)对象的声明(称作异常声明,exception declaration)以及一个块。当选中了某个catch子句处理异常之后,执行与之对应的块。catch一旦完成,程序跳转到try语句块最后一个catch子句之后的那条语句继续执行。一如往常,try语句块声明的变量在块外部无法访问,特别是在catch子句内也无法访问。如果一段程序没有try语句块且发生了异常,系统会调用terminate函数并终止当前程序的执行。

    (3)、一套异常类(exception class):用于在throw表达式和相关的catch子句之间传递异常的具体信息。

    函数在寻找处理代码的过程中退出:寻找处理代码的过程与函数调用链刚好相反。当异常被抛出时,首先搜索抛出该异常的函数。如果没有找到匹配的catch子句,终止该函数,并在调用该函数的函数中继续寻找。如果还是没有找到匹配的catch子句,这个新的函数也被终止,继续搜索调用它的函数。以此类推,沿着程序的执行路径逐层回退,直到找到适当类型的catch子句为止。如果最终还是没能找到任何匹配的catch子句,程序转到名为terminate的标准库函数。该函数的行为与系统有关,一般情况下,执行该函数将导致程序非正常退出。

    如果一段程序没有try语句块且发生了异常,系统会调用terminate函数并终止当前程序的执行。

    那些在异常发生期间正确执行了”清理”工作的程序被称作异常安全(exception safe)的代码。编写异常安全的代码非常困难。

    标准异常:C++标准库定义了一组类,用于报告标准库函数遇到的问题。这些异常类也可以在用户编写的程序中使用,它们分别定义在4个头文件中:

    (1)、exception头文件定义了最通常的异常类std::exception,它只报告异常的发生,不提供任何额外的信息。

    (2)、stdexcept头文件定义了几种常用的异常类,如下:

    (3)、new头文件定义了bad_alloc异常类型。

    (4)、type_info头文件定义了bad_cast异常类型。

    标准库异常类只定义了几种运算,包括创建或拷贝异常类型的对象,以及为异常类型的对象赋值。我们只能以默认初始化的方式初始化exception、bad_alloc和bad_cast对象,不允许为这些对象提供初始值。其它异常类型的行为则恰恰相反:应该使用string对象或者C风格字符串初始化这些类型的对象,但是不允许使用默认初始化的方式。当创建此类对象时,必须提供初始值,该初始值含有错误相关的信息。

    异常类型只定义了一个名为what的成员函数,该函数没有任何参数,返回值是一个指向C风格字符串的const char*。该字符串的目的是提供关于异常的一些文本信息。what函数返回的C风格字符串的内容与异常对象的类型有关。如果异常类型有一个字符串初始值,则what返回该字符串。对于其它无初始值的异常类型来说,what返回的内容由编译器决定。

    异常处理(exception handling)机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并做出相应的处理。异常使得我们能够将问题的检测与解决过程分离开来。程序的一部分负责检测问题的出现,然后解决该问题的任务传递给程序中的另一部分。检测环节无须知道问题处理模块的所有细节,反之亦然。

    抛出异常:在C++语言中,我们通过抛出(throwing)一条表达式来引发(raised)一个异常。被抛出的表达式的类型以及当前的调用链共同决定了哪段处理代码(handler)将被用来处理该异常。被选中的处理代码是在调用链中与抛出对象类型匹配的最近的处理的代码。其中,根据抛出对象的类型和内容,程序的异常抛出部分将会告知异常处理部分到底发生了什么错误。

    当执行一个throw时,跟在throw后面的语句将不再被执行,throw语句的用法有点类似于return语句:它通常作为调节语句的一部分或者作为某个函数的最后(或者唯一)一条语句。相反,程序的控制权从throw转移到与之匹配的catch模块。该catch可能是同一个函数中的局部catch,也可能位于直接或间接调用了发生异常的函数的另一个函数中。

    当抛出一个异常后,程序暂停当前函数的执行过程并立即开始寻找与异常匹配的catch子句。当throw出现在一个try语句块内时,检查与该try块关联的catch子句。如果找到了匹配的catch,就使用该catch处理异常。如果这一步没找到匹配的catch且该try语句嵌套在其它try块中,则继续检查与外层try匹配的catch子句。如果还是找不到匹配的catch,则退出当前的函数,在调用当前函数的外层函数中继续寻找,依次类推。这一过程被称为栈展开(stack unwinding)过程。栈展开过程沿着嵌套函数的调用链不断查找,直到找到了与异常匹配的catch子句为止:或者也可能一直没找到匹配的catch,则退出主函数后查找过程终止。

    假设找到了一个匹配的catch子句,则程序进入该子句并执行其中的代码。当执行完这个catch子句后,找到与try块关联的最后一个catch子句之后的点,并从这里继续执行。如果没找到匹配的catch子句,程序将退出。因为异常通常被认为是妨碍程序正常执行的事件,所以一旦引发了某个异常,就不能对它置之不理。当找不到匹配的catch时,程序将调用标准库函数terminate,terminate负责终止程序的执行过程。

    Note:一个异常如果没有被捕获,则它将终止当前的程序

    栈展开过程中对象被自动销毁:在栈展开过程中,位于调用链上的语句块可能会提前退出。通常情况下,程序在这些块中创建了一些局部对象。块退出后它的局部对象也将随之销毁,这条规则对于栈展开过程同样适用。如果在栈展开过程中退出了某个块,编译器将负责确保在这个块中创建的对象能被正确地销毁。如果某个局部对象的类型是类类型,则该对象的析构函数将被自动调用。与往常一样,编译器在销毁内置类型的对象时不需要做任何事情。

    析构函数与异常:析构函数总是会被执行的。出于栈展开可能使用析构函数的考虑,析构函数不应该抛出不能被它自身处理的异常。换句话说,如果析构函数需要执行某个可能抛出异常的操作,则该操作应该被放置在一个try语句块当中,并且在析构函数内部得到处理。一旦在栈展开的过程中析构函数抛出了异常,并且析构函数自身没能捕获到异常,则程序将被终止。

    异常对象(exception object):是一种特殊的对象,编译器使用异常抛出表达式来对异常对象进行拷贝初始化。因此,throw语句中的表达式必须拥有完全类型。而且如果该表达式是类类型的话,则相应的类必须含有一个可访问的析构函数和一个可访问的拷贝或移动构造函数。如果该表达式是数组类型或函数类型,则表达式将被转换成与之对应的指针类型。异常对象位于由编译器管理的空间中,编译器确保无论最终调用的是哪个catch子句都能访问该空间。当异常处理完毕后,异常对象被销毁。如果退出了某个块,则同时释放块中局部对象使用的内存。因此,抛出一个指向局部对象的指针几乎肯定是一种错误的行为。出于同样的原因,从函数中返回指向局部对象的指针也是错误的。当我们抛出一条表达式时,该表达式的静态编译时类型决定了异常对象的类型。如果一条throw表达式解引用一个基类指针,而该指针实际指向的是派生类对象,则抛出的对象将被切掉一部分,只有基类部分被抛出。

    捕获异常:catch子句(catch clause)中的异常声明(exception declaration)看起来像是只包含一个形参的函数形参列表。像在形参列表中一样,如果catch无须访问抛出的表达式的话,则我们可以忽略捕获形参的名字。声明的类型决定了处理代码所能捕获的异常类型.这个类型必须是完全类型,它可以是左值引用,但不能是右值引用。

    当进入一个catch语句后,通过异常对象初始化异常声明中的参数。和函数的参数类似,如果catch的参数类型是非引用类型,则该参数是异常对象的一个副本,在catch语句内改变参数实际上改变的是局部副本而非异常对象本身;相反,如果参数是引用类型,则和其它引用参数一样,该参数是异常对象的一个别名,此时改变参数也就是改变异常对象。

    catch的参数还有一个特性也与函数的参数非常类似:如果catch的参数是基类类型,则我们可以使用其派生类类型的异常对象对其进行初始化。此时,如果catch的参数是非引用类型,则异常对象将被切掉一部分,这与将派生类对象以值传递的方式传给一个普通函数差不多。另一方面,如果catch的参数是基类的引用,则该参数将以常规方式绑定到异常对象上。

    异常声明的静态类型将决定catch语句所能执行的操作。如果catch的参数是基类类型,则catch无法使用派生类特有的任何成员。

    通常情况下,如果catch接受的异常与某个继承体系有关,则最好将该catch的参数定义成引用类型

    查找匹配的处理代码:在搜索catch语句的过程中,我们最终找到的catch未必是异常的最佳匹配。相反,挑选出来的应该是第一个与异常匹配的catch语句。因此,越是专门的catch越应该置于整个catch列表的前端。因为catch语句是按照其出现的顺序逐一进行匹配的,所以当程序使用具有继承关系的多个异常时必须对catch语句的顺序进行组织和管理,使得派生类异常的处理代码出现在基类异常的处理代码之前。

    与实参和形参的匹配规则相比,异常和catch异常声明的匹配规则受到更多限制。此时,绝大多数类型转换都不被允许,除了一些极细小的差别之外,要求异常的类型和catch声明的类型是精确匹配的:

    (1)、允许在非常量向常量的类型转换,也就是说,一条非常量对象的throw语句可以匹配一个接受常量引用的catch语句。

    (2)、允许从派生类向基类的类型转换。

    (3)、数组被转换成指向数组(元素)类型的指针,函数被转换成指向该函数类型的指针。

    除此之外,包括标准算术类型转换和类类型转换在内,其它所有转换规则都不能在匹配catch的过程中使用。

    如果在多个catch语句的类型之间存在着继承关系,则我们应该把继承链最低端的类(most derived type)放在前面,而将继承链最顶端的类(least derived type)放在后面

    重新抛出:有时,一个单独的catch语句不能完整地处理某个异常。在执行了某些校正操作之后,当前的catch可能会决定由调用链更上一层的函数接着处理异常。一条catch语句通过重新抛出(rethrowing)的操作将异常传递给另外一个catch语句。这里的重新抛出仍然是一条throw语句,只不过不包含任何表达式:throw;

    空的throw语句只能出现在catch语句或catch语句直接或间接调用的函数之内。如果在处理代码之外的区域遇到了空throw语句,编译器将调用terminate。

    一个重新抛出语句并不指定新的表达式,而是将当前的异常对象沿着调用链向上传递。

    很多时候,catch语句会改变其参数的内容。如果在改变了参数的内容后catch语句重新抛出异常,则只有当catch异常声明是引用类型时我们对参数所做的改变才会被保留并继续传播。

    捕获所有异常的处理代码:为了一次性捕获所有异常,我们使用省略号作为异常声明,这样的处理代码称为捕获所有异常(catch-all)的处理代码,形如catch(…)。一条捕获所有异常的语句可以与任意类型的异常匹配。

    catch(…)通常与重新抛出语句一起使用,其中catch执行当前局部能完成的工作,随后重新抛出异常。

    catch(…)既能单独出现,也能与其它几个catch语句一起出现。

    如果catch(…)与其它几个catch语句一起出现,则catch(…)必须在最后的位置。出现在捕获所有异常语句后面的catch语句将永远不会被匹配

    函数try语句块与构造函数:通常情况下,程序执行的任何时刻都可能发生异常,特别是异常可能发生在处理构造函数初始值的过程中。构造函数在进入其函数体之前首先执行初始值列表。因为在初始值列表抛出异常时构造函数体内的try语句块还未生效,所以构造函数体内的catch语句无法处理构造函数初始值列表抛出的异常。要想处理构造函数初始值抛出的异常,我们必须将构造函数写出函数try语句块(也称为函数测试块,function try block)的形式。函数try语句块使得一组catch语句既能处理构造函数体(或析构函数体),也能处理构造函数的初始化过程(或析构函数的析构过程)。

    在初始化构造函数的参数时也可能发生异常,这样的异常不属于函数try语句块的一部分。函数try语句块只能处理构造函数开始执行后发生的异常。和其它函数调用一样,如果在参数初始化的过程中发生了异常,则该异常属于调用表达式的一部分,并将在调用者所在的上下文中处理。

    处理构造函数初始值异常的唯一方法是将构造函数写成函数try语句块

    noexcept异常说明:在C++11新标准中,我们可以通过提供noexcept说明(noexcept specification)指定某个函数不会抛出异常。其形式是关键字noexcept紧跟在函数的参数列表后面,用以标识该函数不会抛出异常。

    对于一个函数来说,noexcept说明要么出现在该函数的所有声明语句和定义语句中,要么一次也不出现。该说明应该在函数的尾置返回类型之前。我们也可以在函数指针的声明和定义中指定noexcept。在typedef或类型别名中则不能出现noexcept。在成员函数中,noexcept说明符需要跟在const及引用限定符之后,而在final、override或虚函数的=0之前。

    违反异常说明:如果一个函数在说明了noexcept的同时又含有throw语句或者调用了可能抛出异常的其它函数,编译器将顺利编译通过,并不会因为这种违反异常说明的情况而报错(不排除个别编译器会对这种用法提出警告)。一旦一个noexcept函数抛出了异常,程序就会调用terminate以确保遵守不在运行时抛出异常的承诺。noexcept可以用在两种情况下,一是我们确认函数不会抛出异常;二是我们根本不知道该如何处理异常。

    通常情况下,编译器不能也不必在编译时验证异常说明。

    如果函数被设计为是throw()的,则意味着该函数将不会抛出异常:void f(int) throw();

    异常说明的实参:noexcept说明符接受一个可选的实参,该实参必须能转换为bool类型:如果实参是true,则函数不会抛出异常;如果实参是false,则函数可能抛出异常。

    noexcept运算符:noexcept说明符的实参常常与noexcept运算符(noexcept orerator)混合使用。noexcept运算符是一个一元运算符,它的返回值是一个bool类型的右值常量表达式,用于表示给定的表达式是否会抛出异常。和sizeof类似,noexcept也不会求其运算对象的值。

    noexcept有两层含义:当跟在函数参数列表后面时它是异常说明符;而当作为noexcept异常说明的bool实参出现时,它是一个运算符

    异常说明与指针、虚函数和拷贝控制:尽管noexcept说明符不属于函数类型的一部分,但是函数的异常说明仍然会影响函数的使用。函数指针及该指针所指的函数必须具有一致的异常说明。也就是说,如果我们为某个指针做了不抛出异常的说明,则该指针将只能指向不抛出异常的函数。相反,如果我们显示或隐式地说明了指针可能抛出异常,则该指针可以指向任何函数,即使是承诺了不抛出异常的函数也可以。

    如果一个虚函数承诺了它不会抛出异常,则后续派生出来的虚函数也必须做出同样的承诺;与之相反,如果基类的虚函数允许抛出异常,则派生类的对应函数既可以允许抛出异常,也可以不允许抛出异常。

    当编译器合成拷贝控制成员时,同时也生成一个异常说明。如果对所有成员和基类的所有操作都承诺了不会抛出异常,则合成的成员是noexcept的。如果合成成员调用的任意一个函数可能抛出异常,则合成的成员是noexcept(false)。而且,如果我们定义了一个析构函数但是没有为它提供异常说明,则编译器将合成一个。合成的异常说明将与假设由编译器为类合成析构函数时所得的异常说明一致。

    异常类层次:标准库异常类构成了下图所示的继承体系:

    类型exception仅仅定义了拷贝构造函数、拷贝赋值运算符、一个虚析构函数和一个名为what的虚成员。其中what函数返回一个const char*,该指针指向一个以null结尾的字符数组,并且确保不会抛出任何异常。

    类exception、bad_cast和bad_alloc定义了默认构造函数。类runtime_error和logic_error没有默认构造函数,但是有一个可以接受C风格字符串或者标准库string类型实参的构造函数,这些实参负责提供关于错误的更多信息。在这些类中,what负责返回用于初始化异常对象的信息。因为what是虚函数,所以当我们捕获基类的引用时,对what函数的调用将执行与异常对象动态类型对应的版本。

    实际的应用程序通常会自定义exception(或者exception的标准库派生类)的派生类以扩展其继承体系。这些面向应用的异常类表示了与应用相关的异常条件。和其它继承体系一样,异常类也可以看作按照层次关系组织的。层次越低,表示的异常情况就越特殊。例如,在异常类继承体系中位于最顶层的通常是exception,exception表示的含义是某处出错了,至于错误的细节则未作描述。

    继承体系的第二层将exception划分为两个大的类别:运行时错误和逻辑错误。运行时错误表示的是只有在程序运行时才能检测到的错误;而逻辑错误一般指的是我们可以在程序代码中发现的错误。

    下面是从其他文章中copy的std::exception测试代码,详细内容介绍可以参考对应的reference:

    #include "exception.hpp"
    #include <exception>
    #include <typeinfo>
    #include <iostream>
    #include <utility>
    #include <cstring>
    
    // Fix: error C3646: 'noexcept' : unknown override specifier
    #ifndef _MSC_VER
    #define NOEXCEPT noexcept
    #else
    #define NOEXCEPT
    #endif
    
    namespace exception_ {
    /////////////////////////////////////////////////////////////
    // reference: http://www.cplusplus.com/reference/exception/exception/
    class Polymorphic { 
    	virtual void member(){}
    };
    
    int test_exception_1()
    {
    	try {
    		Polymorphic * pb = 0;
    		typeid(*pb); // throws a bad_typeid exception
    	} catch (std::exception& e) { // std::std::bad_typeid
    		std::cerr << "exception caught: " << e.what() << '\n'; // exception caught: Attempted a typeid of Null pointer!
    	}
    
    	return 0;
    }
    
    struct ooops : std::exception {
    	const char* what()  const NOEXCEPT /*noexcept*/ override{ return "Ooops!\n"; }
    };
    
    int test_exception_2()
    {
    	ooops e;
    	std::exception* p = &e;
    	try {
    		throw e;       // throwing copy-constructs: ooops(e)
    	} catch (std::exception& ex) {
    		std::cout << ex.what(); // 0oops!
    	}
    	
    	try {
    		throw *p;      // throwing copy-constructs: std::exception(*p)
    	} catch (std::exception& ex) {
    		std::cout << ex.what(); // Unknown exception
    	}
    
    	return 0;
    }
    
    // text_exception uses a dynamically-allocated internal c-string for what():
    class text_exception : public std::exception {
    public:
    	text_exception(const char* text) {
    		text_ = new char[std::strlen(text) + 1];
    		std::strcpy(text_, text);
    	}
    	text_exception(const text_exception& e) {
    		text_ = new char[std::strlen(e.text_) + 1];
    		std::strcpy(text_, e.text_);
    	}
    	~text_exception() NOEXCEPT /*throw()*/ {
    		delete[] text_;
    	}
    	const char* what() const NOEXCEPT /*noexcept*/ override { return text_; }
    
    private:
    	char* text_;
    };
    
    int test_exception_3()
    {
    	try {
    		throw text_exception("custom text\n");
    	} catch (std::exception& ex) {
    		std::cout << ex.what(); // custom text
    	}
    
    	return 0;
    }
    
    } // namespace exception_

    GitHubhttps://github.com/fengbingchun/Messy_Test

     

    展开全文
  • 一、前言 前面我们说到有关于API的学习,但是软件程序在运行过程中并不是会非常完美的,比如当我们写某个模块,用户的输入不一定符合要求,程序可能不存在或者是文件格式不对等等。所以接下来我们将要学习java的...

    一、前言

    前面我们说到有关于API的学习,但是软件程序在运行过程中并不是会非常完美的,比如当我们写某个模块,用户的输入不一定符合要求,程序可能不存在或者是文件格式不对等等。所以接下来我们将要学习java的异常捕捉机制

    二、分析学习

    软件程序在运行时,经常会遇到各种各样的问题,我们将其称之为异常:Exception,也就是例外的意思。那么我们怎么样才能使编写的程序安全的退出而不至于程序崩溃呢?我们先来看看用if语句处理程序的原始方案。

    public class TestException0 {
        public static void main(String[] args) {
            //将d:/a.txt复制到e:/a.txt
            if("d:/a.txt"这个文件存在){
                if(e盘的空间大于a.txt文件长度){
                    if(文件复制一半IO流断掉){
                        停止copy,输出:IO流出问题!
                    }else{
                        copyFile("d:/a.txt","e:/a.txt");
                    }
                }else{
                    System.out.println("e盘空间不够存放a.txt!");
                }
            }else{
                System.out.println("a.txt不存在!");
            }
        }
    }
    
    原始的方式下存在的弊端
    1. 逻辑代码处理代码存放在一起。
    2. 程序员要考虑的例外情况很复杂

    逻辑代码与处理代码存放在一起,使得程序员本人找不到正确的执行代码;而且用原始if处理,就要求程序员本身对例外的错误情况十分了解,对程序员的要求十分高。

    那么我们怎么样去应对异常情况呢?JAVA的异常机制就给我们提供了一些方便的处理方式。假如我们使用JAVA的异常机制来处理的话可以类似如下:

    try {
        copyFile("d:/a.txt","e:/a.txt");
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    异常机制的本质

    上面所提到的异常,我们可以直接用try-catch将其包起来,JAVA的异常我们可以交给try异常块给包起来,当我们遇到程序异常时我们直接交给系统处理,直接catch一下。

    我们将JAVA异常机制的本质可以理解为当程序出现错误或异常时,程序能够安全退出的机制。

    三、处理方式

    异常指程序运行过程中出现的非正常现象,例如用户输入错误、除数为零、需要处理的文件不存在、数组下标越界等。

    在Java的异常处理机制中,引进了很多用来描述和处理异常的类,称为异常类
    1
    异常类定义中包含了该类异常的信息和对异常进行处理的方法。
    2
    所谓异常处理,就是指程序在出现问题时依然可以正确的执行完。
    我们开始看我们的第一个异常对象,并分析一下异常机制是如何工作的。

    异常分析(除数为0)
    public class TestException1 {
        public static void main(String[] args) {
            int i=1/0;  //除数为0
            System.out.println(i);//输出
        }
    }
    

    执行结果如下所示:
    3
    我们可以看到,系统提示0不能作除数,当程序跑到异常处时会生成一个”ArithmeticException“异常对象,然后抛给我们的JRE,再由JRE作处理将程序给停止掉,最后提示并打印相关的异常信息,让我们去想办法处理异常。

    Java是采用面向对象的方式来处理异常的。处理过程:
    1. 抛出异常:在执行一个方法时,如果发生异常,则这个方法生成代表该异常的一个对象,停止当前执行路径,并把异常对象提交给JRE。
    2. 捕获异常 :JRE得到该异常后,寻找相应的代码来处理该异常。JRE在方法的调用栈中查找,从生成异常的方法开始回溯,直到找到相应的异常处理代码为止。

    四、异常分类

    JDK 中定义了很多异常类,这些类对应了各种各样可能出现的异常事件,所有异常对象都是派生于Throwable类的一个实例。如果内置的异常类不能够满足需要,还可以创建自己的异常类。

    Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为java.lang.Throwable,Throwable下面又派生了两个子类:ErrorException。Java异常类的层次结构如下所示。
    11


    对于Error来说,我们只有重启虚拟机了,这个无法处理的是不需要再去处理异常了。

    而对于Exception来讲,是我们本次需要学习的异常,在这之下还分为两大类:Checked ExceptionRuntimeExceptionUnchecked Exception),需要检查的异常和不需要检查的异常(运行时会抛出,一般为逻辑错误)

    此张图为异常的基本分类,比较重要,要牢记!下一篇我们来展开讲解异常的分类!

    未完待续~

    展开全文
  • 《Java:详解Java中的异常(Error与Exception)》 《Java:简述Java中的自定义异常》 《Java:简述throw-throws异常抛出》 《Java:简述try-catch-finally异常捕获》 《Java:简述try-catch-finally中return返回》...
  • 3. Exception的恢复

    2020-06-01 17:00:51
    1. 异常的类型 2. Fault类型的异常: 回到异常指令 3. Trap类型的异常: 跳过异常指令 4. Abort类型的异常: shutdown或reset 4.1. #DF(Double Fault)异常 1. 异常的类型 当异常发生, 处理器将进入异常处理程序, ...
  • 页错误(Page Fault)

    2020-04-17 11:00:46
    页错误(Page Fault)
  • 操作系统之中断(四)

    2016-02-16 13:12:20
    上一篇文章中简单的提到了IDT是记录了终端号和中断函数之间的关系,实际上在保护模式下,IDT在中断中的地位举足轻重。一、实模式切换到保护模式IDT是在保护模式中出现的,计算机启动后运行在实模式下,所以需要将CPU...
  • 1. 概述 上篇文章分析到malloc/mmap函数中,内核实现只是在进程的地址空间建立好了vma区域 并没有实际的虚拟地址到物理地址的映射操作。这部分就是在Page Fault异常错误处理中实现的。 Linux内核中的Page Fault异常...
  • 1、什么是异常?  程序开发和运行过程中会出现编译...异常( Exception ):正常程序流程所不能处理或者没有处理的异常情况或异常事件。 2、为什么要使用异常?  传统的程序设计中会像下面的伪代码形式来处理错误:
  • Java之常见异常Exception

    2018-08-15 08:55:30
    异常是程序编译或运行时可能会发生的一些小的错误,如果发生会导致程序正常的运行。 编译期异常是可检查的,编译的时候提醒编程的人要处理,运行期异常是不可检查的  1.... /** * function: 1.2.1编译异常 author:...
  • Java中的Exception和Error有什么区别? 概念 Exception是程序正常运行中预料到可能会发生的错误,并且应该被捕获并进行相应的处理,是一种异常。 Error是正常情况下不可能发生的错误,会导致JVM处以一种不可恢复的...
  • 只不过java里关于Exception的东西实在是很多. 所以这篇文章很长就是了.. 一, 什么是java里的异常 由于java是c\c++ 发展而来的, 首先我们先看看c语言里的错误. 1.1 c语言里的错误  我们实现1个程序的过程包括...
  • 严重: Exception sending context initialized event to listener instance of class org.springfram 意思就是说初始化事件的时候出现了异常 第一步: 1、先检查是否导入了项目所需要的全部Jar包,一般情况下是因为...
  • Exception in thread "main" java.lang.NullPointerException at oj1255.Main.input(Main.java:41) at oj1255.Main.(Main.java:24) at oj1255.Main.main(Main.java:52) 然后我调试才发现,这个对象数组居然...
  • Error类和Exception类的父类都是throwable类,他们的区别是: Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。对于这类错误的导致的应用程序中断,仅靠程序本身无法...
  • 使用Exception可以保证捕获异常后能继续维持JVM的运行 如果Exception换成IOException后,一旦出现IO异常,便会捕获停止运行. “IoException“(流异常,通常用在文件读取中)是”Exception”(用在所有的异常处理中...
  • Java 中定义了两类异常: 1) Checked exception: 这类异常都是Exception的子类 。异常的向上抛出机制进行处理,如果子类可能产生A异常,那么在父类中也必须throws A异常。可能导致的问题:代码效率低,耦合度过高。...
  • 打开ExceptionException的分类先来看看下面这张图: 从图中可以看出: 1. Error(错误)和Exception(异常)都继承自Throwable类,我们重点关注Exception; 2. 异常类分为检查异常(直接继承自Exception,除
  • 心态崩了,电脑又蓝屏了,同样蹦出来UNEXPECTED_STORE_EXCEPTION,like this: 而且我的是卡在完成 0%永远不会动的那种,重启之后就是找不到硬盘,无法从硬盘启动。 在网上搜了一些方法,问题的原因好像是这个...
1 2 3 4 5 ... 20
收藏数 1,891,603
精华内容 756,641
关键字:

exception