380 likes | 539 Views
第 8 章. 异 常处理. 一、程序中的错误. 《 编译错误 》 由于所编写的程序存在语法问题,未能通过由源代码到目标代码的编译过程而产生的错误。它将由语言的编译系统负责检测和报告。 《 运行错误 》 在程序的运行过程中产生的错误。. 二、 Java 对异常的处理机制. Java 使用异常对 Java 程序给出一个统一和相对简单的 抛出 和 处理 错误的机制。如果一个方法本身能抛出异常,当所调用的方法出现异常时,调用者可以 捕获 异常使之得到处理;也可以 回避 异常,这时异常将在调用的堆栈中向下传递,直到被处理。. b. a. c. d. 必须解决.
E N D
第 8 章 异 常处理
一、程序中的错误 • 《编译错误》 • 由于所编写的程序存在语法问题,未能通过由源代码到目标代码的编译过程而产生的错误。它将由语言的编译系统负责检测和报告。 • 《运行错误》 • 在程序的运行过程中产生的错误。
二、Java对异常的处理机制 • Java使用异常对Java程序给出一个统一和相对简单的抛出和处理错误的机制。如果一个方法本身能抛出异常,当所调用的方法出现异常时,调用者可以捕获异常使之得到处理;也可以回避异常,这时异常将在调用的堆栈中向下传递,直到被处理。
b a c d 必须解决 自行解决 或将其抛 出。 发现异常 不自行解 决,将其 抛出。 发现异常 自行处理
Object Throwable Error Exception AWTException IOException RuntimeException 异常类 Error 类对象由 Java 虚拟机生成并抛出; Exception 类对象由应用程序处理或抛出。 Throwable类是类库java.lang包中的一个类
Exception 类的主要方法 public Exception( ); public Exception(String s);可以接受字符串参数传入的信息,该信息通常是对该例外所对应的错误的描述。 • public String toString( );返回描述当前Exception 类信息的字符串。 • public void printStackTrace(); printStackTrace()方法没有返回值,它的功能是完成一个打印操作,在当前的标准输出(一般就是屏幕)上打印输出当前例外对象的堆栈使用轨迹,也即程序先后调用执行了哪些对象或类的哪些方法,使得运行过程中产生了这个例外对象。
三、异常处理 • 对运行时异常可以不做处理,由Java虚拟机自动进行处理; • 使用Try-catch-finally语句捕获处理; • 通过throws子句声明抛弃异常,还可以定义自己的异常类,并用throw 语句抛弃。
1、运行时异常 • 运行时异常是由Java运行时系统在程序的运行过程中检测到的。它可能在程序的任何部位发生,而且其数量可能很大,因此Java编译器允许程序不对它进行处理。这时,Java系统会把生成的运行时异常对象交给缺省的异常处理程序,在标准输出设备上显示异常的内容以及发生异常的位置。
class ArrayOutOf { public static void main(String[ ] args) { char[ ] buf = {'a', 'b', 'c'}; int i; for (i = 0; i < buf.length; i++) System.out.println(buf[i]); System.out.println(buf[i]); } }
public class StringIndexOutOf { public static void main(String args[ ]) { String str = "abc"; System.out.println(str.charAt(3)); } }
2、捕获异常并进行处理 try {调用产生异常的方法及其他java语句;} catch(异常类名 异常对象名) {异常处理;} catch(异常类名 异常对名) {异常处理;} ...... finally {最终处理;}
public class TryCatchFinally { public static void main( String args[ ] ) { Method( 0 ); Method( 1 ); Method( 2 ); } static void Method( int a ) { System.out.println("调用方法 Method("+a+")"); try { if( a==0 ) { System.out.println("\t没有异常产生,正常退出。"); return; } else if( a==1 ) { int i=0; int j=4/i; } else if ( a==2 ) { int iArray[ ]=new int[4]; iArray[4]=3; } }
catch( ArithmeticException e ) { System.out.println("\t捕获异常: "+e); } catch( ArrayIndexOutOfBoundsException e ) { System.out.println("\t捕获异常:"+e.getMessage( )); } catch( Exception e ) { System.out.println(“\t产生的异常已被处理, 该catch块不会被执行。"); } finally { System.out.println("\tfinally块总是被执行。"); } } }
3、抛出异常 • 在有些情况下,一个方法并不需要处理它所生成的异常,而是向上传递,由调用它的方法来处理这些异常,这时就要用到throw子句。其格式如下: 返回类型 方法名([参数表]) throw 异常名列表
public class throws Exception { public static void main( String args[] ) { try { Method( 0 ); Method( 1 ); } catch(NumberFormatException e ) {System.out.println("\t捕获异常:"+e);} catch( ArrayIndexOutOfBoundsException e ) {System.out.println("\t捕获异常:"+e);} finally {System.out.println(“finally 块总是会被执行.”); } }
static void Method( int i ) throws ArithmeticException,NumberFormatException { System.out.println("调用方法Method("+i+")"); if( i==0 ) { System.out.println(“\t没有异常事件。”); return; } else if( i==1 ) { String str = "xyz"; int c; c=Integer.parseInt(str); } } }
4、抛出异常 • 在捕获异常之前,必须有一段 Java代码生成一个异常对象并将它抛出。异常对象的生成和抛出可以有三种情况: • Java运行时系统; • JDK中某个类; • 在程序中创建异常对象并抛出。
public class TestThrowException { static double sqrt(double i) throws IllegalArgumentException { if (i < 0) { IllegalArgumentException e=new IllegalArgumentException ("Cannot take square root of a negative number"); throw e;} return (Math.sqrt(i)); } public static void main(String[] args) { System.out.println("IllegalArgumentException example"); try { System.out.println(sqrt(-4)); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); } } }
public class TestMyException { static void Method( int a ) throws MyException { System.out.println("调用方法 Method("+a+")"); if( a>10|a<0 ) throw new MyException(a); System.out.println("\t正常退出。"); } public static void main( String args[ ] ) { try { Method( 1 ); Method( -6 );} catch( MyException e ) { System.out.println("\t捕获异常:"+e.toString()); } } }
class MyException extends Exception { private int detail; MyException( int a ) { detail = a; } public String toString( ) { return "MyException "+detail; } }
四、创建用户自己的异常 class 自定义异常 extends 父异常类名 { 类体; } 《举例》 class NumberRangeException extends Exception { NumberRangeException(String msg) { super(msg); } }
class MyException extends Exception{ //自定义的异常类子类MyException public MyException(){ //用户异常的构造函数 } public MyException(String s){ super(s); //调用父类的Exception的构造函数 } public String toString(){ //重载父类的方法,给出详细的错误信息 … } … }
《抛出异常的格式》 [修饰符] 返回类型 方法名(参数1, 参数2,……)throws 自定义异常 { ………….. if(条件满足) throw (new myException(this)); else ……………. }
创建用户自定义异常时,一般需要完成如下的工作:创建用户自定义异常时,一般需要完成如下的工作: • (1)声明一个新的异常类,使之以Exception类或其他某个已经存在的系统异常类或用户异常为父类 • (2)为新的异常类定义属性和方法,或重载父类的属性和方法,使这些属性和方法能够体现该类所对应的错误的信息。
class IllegalSalaryException extends Exception{ //用户定义的工资不合法异常 private Employee m_ConcernedEmp; //产生异常时的Employee类的引用 private double m_IllegalSalary; IllegalSalaryException(Employee emp,double isal){ //构造函数 super("工资低于最低工资"); m_ConcernedEmp=emp; m_IllegalSalary=isal;} public String toString() { //给出具体的错误信息 String s; s="为雇员提供的工资不合法:雇员:"+m_ConcernedEmp.getEmpName() +" 非法工资:"+m_IllegalSalary+" 低于最低工资数额800元"; return s;}}
class IllegalSalaryChangeException extends Exception • {//用户定义的工资变动不合法异常 • private Employee m_ConcernedEmp; • //产生异常时的Employee类的引用 • private double m_IllegalSalaryChange; IllegalSalaryChangeException(Employee emp,double csal) { //构造函数 • super("工资变动太大"); • m_ConcernedEmp=emp; • m_IllegalSalaryChange=csal; } public String toString(){ //给出具体的错误信息 • String s; • s="为雇员提供的工资变动不合法:雇员:"+m_ConcernedEmp.getEmpName()+" 非法变动工资变化:"+m_IllegalSalaryChange+"高于原工资的20%"; • return s; • } }
import java.applet.Applet; • import java.awt.*; • public class UserException extends Applet{ • Employee Emp; • Label prompt1=new Label("请输入雇员姓名和工资初值:"); • Label prompt2=new Label("请输入欲修改的工资:"); • TextField name,isal,nsal; • String msg; • public void init(){ • name=new TextField(5); • isal=new TextField(5); • nsal=new TextField(5); • add(prompt1);add(name);add(isal); • add(prompt2);add(nsal); • } • public void paint(Graphics g){ • g.drawString(msg,0,80); • }
public void CreateEmp(String en,double sa){ • try{ • Emp=new Employee(en,sa); • msg=new String(Emp.toString()); • } • catch(IllegalSalaryException ise){ • msg=new String(ise.toString()); • } • } • public void ChangSal(double cs){ • try{ • Emp.setEmpSalary(cs); • msg=new String(Emp.toString()); • } • catch(IllegalSalaryException ise){ • msg=new String(ise.toString()); • } • catch(IllegalSalaryChangeException isce){ • msg=new String(Emp.toString()+isce.toString()); • } • }
public boolean action(Event e,Object o){ • String en; • double es,cs; • if(e.target==isal){ • en=new String(name.getText()); • es=Double.valueOf(isal.getText()).doubleValue(); • CreateEmp(en,es); • } • else if(e.target==nsal){ • if(Emp!=null){ • cs=Double.valueOf(nsal.getText()).doubleValue(); • ChangSal(cs); • } • else • msg=new String("请先输入雇员姓名工资并创建之"); • } • repaint(); • return true; • } • }
class Employee{ • String m_EmpName; • double m_EmpSalary; • Employee(String name,double initsal) throws IllegalSalaryException{ • m_EmpName=new String(name); • if(initsal<800) • throw(new IllegalSalaryException(this,initsal)); • m_EmpSalary=initsal; • } • public String getEmpName(){ • return m_EmpName; • } • public double getEmpSalary(){ • return m_EmpSalary; • }
public boolean setEmpSalary(double newsal) • throws IllegalSalaryException,IllegalSalaryChangeException • { • if(newsal<800) • throw(new IllegalSalaryException(this,newsal)); • else if(Math.abs(newsal-getEmpSalary())/getEmpSalary()>=0.2) • throw(new IllegalSalaryChangeException(this,newsal-getEmpSalary())); • else{ • m_EmpSalary=newsal; • return true; • } • } • public String toString(){ • String s; • s="姓名:"+m_EmpName+" 工资:"+m_EmpSalary; • return s; • } • }