网站注册平台怎么注册,大连地区网站建设,在网站上做教育直播平台多少钱,土特产网站建设异常处理任何一个软件或程序都可能在运行的过程中出现故障#xff0c;问题的关键是故障出现以后如何处理#xff1f;谁来处理#xff1f;怎样处理#xff1f;处理后系统能否恢复正常的运行#xff1f;本章在介绍Java处理这类问题基本方法的基础上#xff0c;讨论包含异常…异常处理任何一个软件或程序都可能在运行的过程中出现故障问题的关键是故障出现以后如何处理谁来处理怎样处理处理后系统能否恢复正常的运行本章在介绍Java处理这类问题基本方法的基础上讨论包含异常处理的Java程序的设计方法。1、异常和异常处理的两种方法异常是指程序在执行过程中出现的意外事件。异常通常会使程序的正常流程被打断。例如程序在向磁盘中读写文件时磁盘出现问题、算术运算中被除数为0、数组下标越界、输入/输出时文件不存在、输入数据格式不正确、程序本身错误等等。一般情况下程序中需要处理异常情况通过对异常情况的处理可以使程序的执行流程继续下去并进行一些异常处理否则程序的正常执行流程会被中断。1、异常的基本类型异常处理的第一步是确定异常的类型常见的异常情况一般分为以下几类用户输入错误指用户键盘输入错误输入格式不对或输入内容不符合程序要求等。例如用户界面要求输入一个整数而用户输入了一个字符串或者要求用户输入一个URL地址但用户输入的地址语法错误等。设备故障计算机硬件设备有时也会出故障例如打印机没连接好要求的网页没有找到等。物理限制物理设备本身的限制例如硬盘已存满内存已用完等。代码错误程序员编写的代码出现错误例如从一个空的堆栈中弹出元素数组下标为负数等。2、if-else形式的异常处理方法用if-else语句(或switch-case语句)可以发现异常并做出相应处理。例如在程序中要将一个文件整个读入内存通常的步骤是(1)打开文件。(2)判断文件的大小。(3)分配内存。(4)将文件读入内存。(5)关闭文件。在上述的过程中可能出现很多问题例如(1)文件打不开。(2)不能决定文件的大小(3)内存不能分配(4)读入失败(5)文件不能关闭针对这些情况需要在程序中做出相应的处理若用if-else语句则程序伪码如下Class ReadFile{初始化 错误代码 0;打开文件;if (文件可以打开){计算文件的长度;if (文件的长度可以决定){分配内存if (有足够的内存){将文件读入内存if (读入失败){错误代码 读入文件时失败}}else{错误代码 内存不足}}else{错误代码 不能决定文件的大小}关闭文件;if (文件没有关闭 错误代码 0){错误代码 文件关闭失败}}else{错误代码 文件打不开}return错误代码}用if-else语句方式可以发现异常并做出相应的处理。但是程序员由于过多地分析程序中异常情况的发生情况在程序中过多地使用if-else语句会使程序员正常的程序设计思路受到影响。另外程序中过多地使用if-else语句也会影响程序的算法思想的可读性。而且会更为重要的是有些异常情况是不可预见的。例如计算机的连接中断打印机纸张用完等。所以if-else形式不是处理异常的好的方法.3、Java的异常处理方法在Java语言中用try模块和catch模块把程序的正常流程代码和异常处理代码分离。对于上述例子按照Java的异常处理方式伪码表示的程序代码如下Class ReadFile{try{打开文件计算文件的长度分配内存将文件读入内存关闭文件}catch (文件打开失败异常){处理文件打开失败异常}catch (文件的长度不能确定异常){处理文件的长度不能确定异常}catch (分配内存失败异常){处理分配内存失败异常}catch (文件读入内存失败异常){处理文件读入内存失败异常}catch (关闭文件失败异常){处理关闭文件失败异常}}从上述伪码可以看出程序中可能出现的异常情况都放进了try模块中而对于各种异常情况设计了相应的catch模块这些模块可以用来捕捉这些异常情况并进行相应的处理。在Java程序中如果设计人员对可能出现的异常没有设计相应的try模块和catch模块或设计人员无法预见的异常情况系统会将出现的异常交由Java虚拟机(JVM)处理此时Java虚拟机会自动捕捉这些异常情况并将异常情况在屏幕上显示出来。2、Java的异常类Java语言对大多数常见的异常都定义了异常类。这些异常类可以分为两大类Error类和Exception类。Error(错误)类和Exception (异常)类的区别在于错误指的是系统异常或运行环境出现的异常这些异常一般是很严重的异常即使捕捉到通常也无法处理例如Java虚拟机异常。而Exception类的异常指的是一般的异常例如输入/输出(I/O)异常、数据库访问(SQL)异常等。对这些异常应用程序可以进行处理。Java的所有异常类都继承自Throwable类。异常类是Java语言包(java.lang)中的类。Java异常类的继承关系如图所示1、Error类及其子类当系统动态连接失败或者出现虚拟机的其他故障时Java虚拟机会抛出Error错误。程序一般不用捕捉Error错误由系统进行这类错误的捕捉和处理。Error类及其子类定义了系统中大多数这类错误。这里介绍Error类的两个子类及其子类LinkageError(结合错误)类及其子类和VirtualMachineErrror(虚拟机错误)类及其子类。(1)LinkageError类及其子类LinkageError(结合错误)类及其子类定义的是一个类依存于另一个类但在编译前者时后者出现了与前者不兼容情况的各种错误。LinkageError类的子类有ClassFormatError 类格式错误ClassCircularityError 类循环错误NoClassDefFoundError 类定义无法找到错误VerifyError 校验错误AbstractMethodError 抽象方法错误NoSuchFieldError 没有成员变量错误InstantiationError 实例错误(2)VirtualMachineErrror类及其子类VirtualMachineErrror(虚拟机错误)类及其子类定义的是系统在虚拟机损坏或需要运行程序的资源耗尽时出现的各种错误。VirtualMachineErrror类的子类有InternalError 内部错误OutOfMemoryError 内存溢出错误StackOverflowError 堆栈溢出错误UnkownError 未知错误2、Exception类及其子类Exception类及其子类定义了程序中大多数可以处理的异常。这里介绍Exception类的两个子类及其子类RuntimeException (运行时异常)类及其子类和CheckedException (检查异常) 类及其子类。(1)RuntimeException类及其子类RuntimeException(运行时异常)类及其子类定义的是Java程序执行过程中可能出现的各种异常RuntimeException类的子类有ArithmeticException 算术运算异常ArrayStoreException 数组存储异常ArrayIndexOutOfBoundsException 数组下标越界异常CaseCastException 类型转换异常IllegalArgumentException 非法参数异常IllegalThreadStateException 非法线程状态异常NumberFormatException 数字格式异常IlegalMonitorStateException 非法监视状态异常IndexOutofBoundsException 下标超出范围异常NegativeArraySizeEXception 负数组个数异常NullPointerException 空指针异常SecurityException 安全异常EmptyStackException 空栈异常NoSuchElementException 没有元素异常(2)CheckedException 及其子类CheckedException (检查异常)类及其子类定义的是Java程序编译时编译器发现的各种异常。CheckedException类的子类有ClassNotFoundException 类找不到异常CloneNotSupportedException 复制不支持异常IllegalAccessException 非法访问异常InstantiationException 实例异常InterruptedException 中断异常IOException 输入/输出异常FileNotFoundException 文件找不到异常InterruptedIOException 中断输入/输出异常3、Throwable类的方法Error类和Exception类的方法基本都是从Throwable类中继承来的。Throwable类的构造方法主要有Throwable() //构造一个对象其错误信息串为nullThrowable(String message) //构造一个对象其错误信息串为messageThrowable类的方法主要有String getMessage() 返回对象的错误信息void printStackTrace() 输出对象的跟踪信息到标准错误输出流void printStackTrace(PrintStream s) 输出对象的跟踪信息到输出流sString toString() 返回对象的简短描述信息4、异常类的对象应用程序中一旦出现异常系统会产生一个异常类的对象下面讨论的catch语句后面的参数将接收到这样的一个对象。为了语言简洁通常把异常类的对象也简称异常。这就像第6章中我们也把组件类的对象简称组件。3、Java的异常处理方法在Java程序中用try-catch(或try-catch-finally)语句来抛出、捕捉和处理异常。try-catch-finally语句的语法格式是try{可能抛出异常的语句模块}catch (异常类型1){处理异常类型1语句}……catch (异常类型n){处理异常类型n语句}finally{无论是否抛出异常都要执行的语句}try-catch-finally语句的功能为(1)try模块:所有可能抛出异常的语句都放入try模块中。try模块中的语句是程序正常流程要执行的语句但是在执行过程中有可能出现异常。如果像前面程序设计例子那样没有使用try模块则除了系统定义的异常外语句执行过程中出现的其他异常不会被抛出。(2)catch模块:主要负责对抛出的异常做相应的处理。所有抛出的异常都必须是Throwable类或其子类的对象。try模块中的语句可能抛出很多不同类型的异常所以需要针对不同类型的异常分别设计catch模块。一般程序中会有若干个catch模块每一模块处理一种类型的异常。对于这些catch模块其排列的先后顺序有如下规定出现在前面的catch模块中的异常类一定要是后面的catch模块中的异常类的子类 即前面的catch模块中的异常类对象一定比后面的catch模块中的异常类对象特殊。这是因为catch模块是按顺序执行的。如果try模块抛出异常系统会按catch模块的排列次序依次查找如果前面catch模块的异常类型匹配不上就按顺序和后面的catch模块匹配。如果在所有的catch模块中都匹配不上就交给系统的虚拟机由虚拟机来处理这个异常。程序中即使没有try模块若出现了系统定义的异常系统也会自动抛出并由系统负责捕捉和处理但是程序中若有了catch模块则一定要有try模块。另外若用户希望按照自己的意图处理程序中可能出现的系统定义的异常也要在程序中使用try-catch语句否则出现的异常将由系统捕捉和处理。(3)finally模块:finally模块中的语句是必须执行的语句。无论try模块中是否抛出异常finally模块中的语句时都要被执行。这个模块是可选的。如果设计了finally模块通常在这个模块中做一些资源回收的工作。【例8.1】try-catch-finally的执行过程示例。要求设计一个用命令行参数输入数据的程序若该参数的数值输入的不正确会出现异常。程序设计如下public class TryCatchSequence{public static void main(String args[]){int a,b,c;try{a100;bInteger.parseInt(args[0]); //把命令行输入的字符串转换成整数ca/b;System.out.println(cc);System.out.println(No exception.);}catch(ArrayIndexOutOfBoundsException e) //数组下标越界异常{System.out.println(Exception caught!);e.printStackTrace();}catch(ArithmeticException e) //处理算术运算异常{System.out.println(Exception caught!);e.printStackTrace();}finally{System.out.println(Always executed);}}}我们分以下几种情况分别运行上述程序(1) 没有异常抛出。在当前工作目录下键入如下命令(注意该程序正常运行需要从命令行给出参数且该参数值不能为0)java TryCatchSequence 10则程序的运行结果如下c10No exception.Always executed程序的运行结果说明系统执行完了try模块的所有程序 由于程序运行时没有异常抛出所以系统跳过catch模块 最后执行了finally模块。(2)有异常抛出。上述程序可能有如下两种类型的异常发生。--抛出数组下标越界异常。在当前工作目录下键入如下命令(注意该程序运行时无法从命令行得到参数值)java TryCatchSequence程序运行结果如下Exception caught!java.lang.ArrayIndexOutOfBoundsException: 0at TryCatchSequence.main(TryCatchSequence.java:9)Always executed程序的运行结果说明由于命令行没有给出参数在执行语句bInteger.parseInt(args[0]);时系统抛出了数组下标越界异常。程序中处理数组下标越界异常的catch模块匹配上了该异常。程序执行完该catch模块语句后跳过后面的其它catch模块又执行了finally模块中的语句。--抛出算术运算异常。在当前工作目录下键入如下命令(注意该程序运行时从命令行得到的参数值为0)java TryCatchSequence 0程序运行结果如下Exception caught!java.lang.ArithmeticException: / by zeroat TryCatchSequence.main(TryCatchSequence.java:10)Always executed程序的运行结果说明由于命令行给出的参数为0程序中的被除数为0因此运行时系统抛出了算术运算异常。程序中处理算术运算异常的catch模块匹配上了该异常。程序执行完该catch模块语句后跳过后面的其它catch模块又执行了finally模块中的语句。【例8.2】程序中设计的catch模块捕捉不到异常的示例。要求程序中设计了若干catch模块但忽略了其中某种可能发生的异常。程序设计如下public class TryCatchSequence1{public static void main(String args[]){int a,b,c;try{a100;bInteger.parseInt(args[0]);ca/b;System.out.println(cc);System.out.println(No exception.);}catch(ArithmeticException e){System.out.println(Exception caught!);e.printStackTrace();}finally{System.out.println(Always executed);}}}程序设计说明上述程序和例8.1的程序基本相同只是去掉了前面程序的catch(ArrayIndexOutOfBoundsException e)模块。程序运行结果如下Always executedException in thread main java.lang.ArrayIndexOutOfBoundsException: 0at TryCatchSequence2.main(TryCatchSequence2.java:9)程序的运行结果说明程序中出现的ArrayIndexOutOfBoundsException异常不能和程序中的任何catch模块匹配因此交给系统处理系统内置的异常处理模块输出了相应的错误信息。4、异常的抛出和处理系统的异常类定义了很多异常如果程序运行时出现了系统定义的异常系统会自动抛出。此时若应用程序中有try-catch语句则这些异常由系统捕捉并交给应用程序处理若应用程序中没有try-catch语句则这些异常由系统捕捉和处理。对于系统定义的有些应用程序可以处理的异常一般情况下并不希望由系统来捕捉和处理也不希望这种异常造成后果因为这两种情况都有可能造成运行的应用程序产生不良后果。这种情况下设计应用程序的一般方法是在try模块中应用程序自己判断是否有异常出现如果有异常出现则创建异常对象并用throw语句抛出该异常对象在catch模块中设计用户自己希望的异常处理方法。throw语句的语法格式为throw ;这种情况下异常的抛出和处理有两种方式一种是在同一个方法中抛出异常和处理异常另一种是在一个方法中抛出异常在调用该方法的方法中处理异常。1、在同一个方法中抛出异常和处理异常在同一个方法中抛出异常和处理异常。应用程序中大部分异常的抛出和异常的处理采用这种设计方法。【例8.3】在同一个方法中抛出异常和处理异常示例。要求设计一个堆栈类堆栈类中要求有一个入栈方法该方法向堆栈中加入一个元素。当调用入栈方法且堆栈已满时会出现堆栈已满异常。处理异常的模块捕捉到该异常后显示异常信息后退出系统。程序设计如下class SeqStack //堆栈类{int data[]; //成员变量存放元素int MAX; //成员变量数组个数int top; //成员变量当前元素个数SeqStack(int m) //构造方法{MAX m; //为MAX赋值mdata new int[MAX]; //创建数组对象datatop 0; //初始值为0}public void push(int item) //入栈方法{try //try模块{if(top MAX) //判断是否有异常产生throw new Exception(stackFull); //抛出异常对象data[top] item; //在堆栈中加入元素itemtop; //元素个数加1}catch(Exception e) //catch模块{System.out.println(exception:e.getMessage());System.exit(0);}}public static void main(String args[]){SeqStack stack new SeqStack(10); //创建对象stackfor(int i 0; i 11; i)stack.push(i); //调用push()方法}}程序运行结果如下exception:stackFull程序设计说明(1)main()中第一条语句创建的对象stack的数组个数MAX为10但循环语句最后一次执行时要向对象stack的数组data中加入第11个元素所以此时会产生异常。(2)由于push()方法中的异常情况(top MAX)不是系统定义的异常所以系统不会抛出该异常需要在该方法中用throw语句自己抛出异常。(3)抛出异常语句throw new Exception(stackFull)首先调用Exception类的构造方法创建一个异常信息为stackFull的异常对象然后抛出该异常。(4)push()方法中的catch模块捕捉到异常后进行了所要求的异常处理。2、抛出异常和处理异常的方法不是同一个如果抛出异常的方法和处理异常的方法不是同一个方法时则要求在抛出异常的方法定义后加如下语句throws Exception然后把catch模块放在调用该方法的方法中。throws Exception语句的功能是在调用方法和可能产生异常的被调用方法之间建立起系统处理异常所需的联系。【例8.4】抛出异常和处理异常的方法不是同一个示例。要求问题同例8.3但要求抛出异常和处理异常的方法不是同一个。程序设计如下class SeqStack2{int data[];int MAX;int top;SeqStack2(int m){MAX m;data new int[MAX];top 0;}public void push(int item) throws Exception //加throws语句{if(top MAX) //判断是否有异常产生throw new Exception(stackFull); //抛出异常data[top] item;top;}public static void main(String args[]){SeqStack2 stack new SeqStack2(10);try //try模块{for(int i 0; i 11; i)stack.push(i);}catch(Exception e) //catch模块{System.out.println(exception:e.getMessage());System.exit(0);}}}程序运行结果和例8.3相同。需要说明的是此例子只是为了说明此种设计方法像例8.3这类问题应用程序的异常抛出和异常处理通常采用前一种设计方法。但是Java API中的许多可能出现异常的方法都采用此种设计方法。例如第9章讨论的输入输出流类中的许多方法在调用时都可能出现异常而调用这些方法的方法是在用户编写的应用程序中Java API不可能设计出适合所有应用情况的异常处理方法因此Java API的这些方法中没有设计try模块和catch模块只是在方法定义后添加了throws语句。如下方法定义就是一个例子public void close() throws IOException//表示close()方法可能抛出IOException异常如果应用程序调用该方法一般情况下要在调用方法中设计try模块和catch模块来处理IOException异常。IOException类是Exception类的一个子类。5、自定义的异常类应用程序中除了可能出现系统定义的异常外有时还可能出现系统没有考虑的异常。此时需要在应用程序中自定义异常类。一般情况下自定义的异常类都是一些应用程序可以处理的异常。所以自定义的异常类一般是Exception类的子类。【例8.5】自定义的异常类示例。class UserDefinedException extends Exception{String msg;public UserDefinedException(){this.msg ;}public UserDefinedException(String s){this.msg s;}}例8.5中用户自己定义的异常类UserDefinedException继承了类Exception类UserDefinedException中定义了两种情况的异常一种的参数为空另一种的参数为字符串s。-The End-