Java程序设计 Java Programming Spring, 2013 Contents Why Exceptions? What are Exceptions? Handling Exceptions Creating Exception Types chapter 8 Exceptions 2/47 Why Exceptions(异常)? During execution(执行), programs can run into many kinds of errors; What do we do when an error occurs? Java uses exceptions to provide the error-handling capabilities for its programs. chapter 8 Exceptions 3/47 Exceptions (异常) 1. Error Class 2. Critical(严重的) error which is not acceptable in normal application program. Exception Class Possible exception in normal application program execution; Possible to handle by programmer. chapter 8 Exceptions 4/47 Exceptions (异常) An exception is an event(事件) that occurs during the execution of a program that disrupts(使中断) the normal flow(流程) of instructions(指令). chapter 8 Exceptions 5/47 Exceptions (异常) Treat exception as an object . All exceptions are instances of a class extended from Throwable class or its subclass. Generally, a programmer makes new exception class to extend the Exception class which is a subclass of Throwable class. chapter 8 Exceptions 6/47 Exception Class 继承关系 Object Throwable Error Exception RuntimeException IOException 7 异常类的层次结构: 8 Classifying(分类) Java Exceptions 1. Unchecked Exceptions(非检查性异常) • It is not required that these types of exceptions be caught or declared on a method. – – Runtime exceptions can be generated by methods or by the JVM itself. Errors are generated from deep within the JVM, and often indicate a truly fatal state. 2. Checked Exceptions(检查性异常) • Must either be caught by a method or declared in its signature by placing exceptions in the method signature. 9 Exception的分类 非检查性异常(unchecked exception): 以RuntimeException为代表的一些类,编译时发现不了, 只在能运行时才能发现。 检查性异常(checked exception): 一般程序中可预知的问题,其产生的异常可能会带来意想 不到的结果,因此Java编译器要求Java程序必须捕获或声 明所有的非运行时异常。 以IOException为代表的一些类。如果代码中存在检查性 异常,必须进行异常处理,否则编译不能通过。如:用户 连接数据库SQLException、FileNotFoundException。 chapter 8 Exceptions 10/47 Exception的分类 什么是Runtime Exception: Java虚拟机在运行时生成的异常,如:被0除等系统错误、 数组下标超范围等,其产生比较频繁,处理麻烦,对程序 可读性和运行效率影响太大。因此由系统检测, 用户可不 做处理,系统将它们交给默认的异常处理程序(当然,必要 时,用户可对其处理)。 Java程序异常处理的原则是: 1. 2. 对于Error和RuntimeException,可以在程序中进行捕 获和处理,但不是必须的。 对于IOException及其他异常,必须在程序进行捕获和处 理。异常处理机制主要处理检查性异常。 chapter 8 Exceptions 11/47 Java Exception Type Hierarchy(层次) virtual machine errors 12 系统异常类的层次结构: chapter 8 Exceptions 13/47 Exception的分类 1. 2. System-Defined Exception(系统定义的异常) Programmer-Defined Exception(程序员自定 义异常) chapter 8 Exceptions 14/47 System-Defined Exception (系统定义的异常) Raised implicitly by system because of illegal execution of program; Created by Java System automatically; Exception extended from Error class and RuntimeException class. chapter 8 Exceptions 15/47 System-Defined Exception IndexOutOfBoundsException: ArrayStoreException: When refer to object as a null pointer SecurityException: When using a negative size of array NullPointerException: When assign object of incorrect type to element of array NegativeArraySizeException: When beyond the bound of index in the object which use index, such as array, string, and vector When violate security. Caused by security manager IllegalMonitorStateException: When the thread which is not owner of monitor involves wait or notify method 16/47 Programmer-Defined Exception (程序员自定义异常) Exceptions raised by programmer Subclass of Exception class Check by compiler whether the exception handler for exception occurred exists or not If there is no handler, it is error. chapter 8 Exceptions 17/47 User-defined Exceptions (用户自定义异常) Creating Exception Types: class UserErr extends Exception { … } 18/47 Example 1: public class InsufficientFundsException extends Exception { private BankAccount excepbank; private double excepAmount; InsufficientFundsException(Bank ba, double dAmount) { excepbank=ba; excepAmount=dAmount; } } chapter 8 Exceptions 19/47 程序运行时发生异常,系统会抛出异常,如果程序中未处理 和捕获异常,异常抛出后程序运行中断。 public class Test { public int[ ] bar() { int a[ ] = new int[2]; for (int x = 0; x <= 2; x++) { a[x] = 0; //抛出异常,程序中断 } return a; } public static void main(String[] args) { Test t = new Test(); t.bar(); //程序中断 System.out.println(“Method: foo”); //不被执行 } } 系统给出的错误信息: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2 at exception.Test.bar(Test.java:7) at exception.Test.main(Test.java:25) 20 Handling Exceptions(处理异常) 1. Throwing an exception(抛出异常) 2. When an error occurs within a method. An exception object is created and handed off to the runtime system(运行时系统). The runtime system must find the code to handle the error. Catching an exception(捕获异常) The runtime system(运行时系统) searches for code to handle the thrown exception. It can be in the same method or in some method in the call(调用) stack(堆栈). chapter 8 Exceptions 21/47 Keywords for Java Exceptions try Marks the start of a block associated with a set of exception handlers. catch If the block enclosed by the try generates an exception of this type, control moves here; watch out for implicit subsumption. finally Always called when the try block concludes, and after any necessary catch handler is complete. throws Describes the exceptions which can be raised by a method. throw Raises an exception to the first available handler in the call stack, unwinding the stack along the way. 22/47 抛出异常– throw, throws 在一个方法的运行过程中,如果一个语句引起了 错误时,含有这个语句的方法就会创建一个包含 有关异常信息的异常对象,并将它传递给Java 运行时系统。 我们把生成异常对象并把它提交给运行时系统的 过程称为抛出(throw)异常。 1. 2. throw — 在方法体中用throw手工抛出异常; throws — 在方法头部间接抛出异常,即:申明 方法中可能抛出的异常。 23/47 1. 在方法体中用throw手工抛出 异常 throw抛出异常,可以是系统定义的异常,也可以是用户自 定义的异常。 语法格式: throw new 异常类构造函数; 或 异常类名 对象名 =new 异常类构造函数; throw 对象名; 例如:下面语句就抛出了一个IOException异常: throw new IOException(); 24/47 throw -Example class ThrowStatement extends Exception { public static void exp(int ptr) { try{ if (ptr == 0) throw new NullPointerException(); } catch(NullPointerException e) { } } } public static void main(String[] args) { int i = 0; ThrowStatement.exp(i); } 25/47 2. throws—间接抛出异常(申明异常) 一个方法不处理它产生的异常,而是沿着调用层次向上传递,由 调用它的方法来处理这些异常,叫声明异常。 在定义方法时用throws关键字将方法中可能产生的异常间接抛 出。 若一个方法可能引发一个异常,但它自己却没有处理,则应该 声明异常,并让其调用者来处理这个异常,这时就需要用 throws关键字来指明方法中可能引发的所有异常。 类型 方法名(参数列表) throws 异常列表 { //…代码 } 26/47 Example 1: public class ExceptionTest{ void Proc(int sel) throws ArrayIndexOutOfBoundsException { System.out.println(“In Situation" + sel ); if(sel==1) { int iArray[ ]=new int[4]; iArray[10]=3; //抛出异常 } } } 27 异常向上传递-Example class ThrowStatement extends Exception { public static void exp(int ptr) throws NullPointerException { if (ptr == 0) throw new NullPointerException(); } } public static void main(String[] args) { int i = 0; ThrowStatement.exp(i); } 运行结果: java.lang.NullPointerException at ThrowStatement.exp(ThrowStatement.java:4) at ThrowStatement.main(ThrowStatement.java:8) 28/47 Exceptions - throwing multiple(多个) exceptions A Method can throw multiple exceptions. Multiple exceptions are separated by commas after the throws keyword: public class MyClass { public int computeFileSize() throws IOException, ArithmeticException { ... } } 29 Handling Exceptions 在一个方法中,对于可能抛出的异常,处理方式 有两种: 1. 2. 一个方法不处理它产生的异常,只在方法头部声明 使用throws抛出异常,使异常沿着调用层次向上 传递,由调用它的方法来处理这些异常。 用try-catch-finally语句对异常及时处理; 30/47 Handling Exceptions public void replaceValue(String name, Object value) throws NoSuchAttributeException { Attr attr=find(name); if(attr==null) throw new NoSuchAttributeException(name); } attr.setValue(value); try{ 当replaceValue(…) 方法被调用时,调用者 需处理异常。 … replaceValue(“att1”, “newValue”); … }catch(NoSuchAttributeException e){ e.printStackTrace(); } 31 处理异常语句try-catch-finally的基本格式为: try { //可能产生异常的代码; } //不能有其它语句分隔 catch(异常类名 异常对象名) { // 异常处理代码; //要处理的第一种异常 } catch(异常类名 异常对象名) { //异常处理代码; //要处理的第二种异常 } … finally { //最终处理(缺省处理) } 32 Exceptions –Syntax(语法)示例 try { // Code which might throw an exception // ... } catch(FileNotFoundException x) { // code to handle a FileNotFound exception } catch(IOException x) { // code to handle any other I/O exceptions } catch(Exception x) { // Code to catch any other type of exception } finally { // This code is ALWAYS executed whether an exception was thrown // or not. A good place to put clean-up code. ie. close // any open files, etc... } 33 Handling Exceptions(处理异常) • • try-catch 或 try-catch-finally . Three statements help define how exceptions are handled: 1. try • identifies a block of statements within which an exception might be thrown; • A try statement can have multiple catch statements associated with it. 2. catch • must be associated with a try statement and identifies a block of statements that can handle a particular type of exception. • The statements are executed if an exception of a particular type occurs within the try block. 34 Handling Exceptions 3. finally (可选项) – must be associated with a try statement and identifies a block of statements that are executed regardless of whether or not an error occurs within the try block. – Even if the try and catch block have a return statement in them, finally will still run. 35 用try-catch-finally语句对异常及时处理-Example class ThrowStatement extends Exception { public static void exp(int ptr) { try{ if (ptr == 0) throw new NullPointerException(); } catch(NullPointerException e){ } } } public static void main(String[] args) { int i = 0; ThrowStatement.exp(i); } 36 系统抛出异常后,捕获异常,运行finally块,程序运行继续。 public class Test { public void foo() { try { int a[ ] = new int[2]; a[4] = 1; /* causes a runtime exception due to the index */ System.out.println(“Method: foo”);//若异常发生,不执行 } catch (ArrayIndexOutOfBoundsException e) { System.out.println("exception: " + e.getMessage()); e.printStackTrace(); }finally { System.out.println("Finally block always execute!!!"); } } public static void main(String[] args) { Test t = new Test(); t.foo(); System.out.println(“Excecution after Exception!!!”); //继续执行 } } 37 运行结果: exception: 4 java.lang.ArrayIndexOutOfBoundsException: 4 at exception.Test.foo(Test.java:8) at exception.Test.main(Test.java:20) Finally block always execute!!! Excecution after Exception!!! 38 Exceptions -throwing multiple exceptions public void method1() { MyClass anObject = new MyClass(); try { int theSize = anObject.computeFileSize(); } catch(ArithmeticException x) { // ... } catch(IOException x) { // ... } } 39 Exceptions -catching multiple exceptions Each try block can catch multiple exceptions. Start with the most specific exceptions FileNotFoundException is a subclass of IO Exception It MUST appear before IOException in the catch list public void method1() { FileInputStream aFile; try { aFile = new FileInputStream(...); int aChar = aFile.read(); //... }catch(FileNotFoundException x) { // ... }catch(IOException x) { // ... } } 40 Exception -The catch-all Handler Since all Exception classes are a subclass of the Exception class, a catch handler which catches "Exception" will catch all exceptions. It must be the last in the catch List. public void method1(){ FileInputStream aFile; try { aFile = new FileInputStream(...); int aChar = aFile.read(); //... } catch(IOException x){ // ... } catch(Exception x){ // Catch All Exceptions } } 41 User-defined Exceptions(用户自定义异常)的处理 用户自定义异常是检查性异常(checked exception), 必须用throw手工抛出并处理。 class UserErr extends Exception { … } class UserClass { … UserErr x = new UserErr(); ... if (val < 1) throw x; } 42 //ThrowExample.java class IllegalValueException extends Exception { } class UserTrial{ int val1,val2; public UserTrial(int a,int b){ val1=a; val2=b; } void show() throws IllegalValueException { if ((val1<0) ||(val2>0)) throw new IllegalValueException(); System.out.println(“Value1=”+ val1);//不运行 System.out.println("Value2 ="+val2); } } class ThrowExample{ public static void main(String args[ ]) { UserTrial values=new UserTrial(-1,1); try{ values.show(); } catch (IllegalValueException e){ System.out.println("Illegal Values: Caught in main"); } } } 输出: Illegal Values: Caught in main 43 Exception Propagation(传递) An exception can be handled at a higher level if it is not appropriate to handle it where it occurs. Exceptions propagate up through the method calling hierarchy until they are caught and handled or until they reach the level of the main method. A try block that contains a call to a method in which an exception is thrown can be used to catch that exception. chapter 8 Exceptions 44/47 Exception Propagation (传递) Exception Propagation Order If there is no catch block to deal with the exception, it is propagated to calling method(调用方法) All executions are ignored until finding the exception handler [Propagate.java] chapter 8 Exceptions 45/47 Exception Propagation public class Propagate { void orange() { ArithmeticException Occurred int m = 25, i = 0; i = m / i; } void apple() { orange(); } public static void main(String[] args) { Propagate p = new Propagate(); p.apple(); } Output by Default Exception } Handler java.lang.ArithmeticException: / by zero at Propagate.orange(Propagate.java:4) at Propagate.apple(Propagate.java:8) at Propagate.main(Propagate.java:11) 46 小结:异常处理机制 1. 在方法声明首部用throws声明抛出异常:异常处 理机制采用谁调用,谁就负责处理被调用方法抛出 的异常。 2. 在方法体中用throw手工抛出异常。 3. 使用try…catch…finally结构对异常进行捕获和处 理。 47