第 8 章
DESCRIPTION
第 8 章. 异 常处理. 一、程序中的错误. 《 编译错误 》 由于所编写的程序存在语法问题,未能通过由源代码到目标代码的编译过程而产生的错误。它将由语言的编译系统负责检测和报告。 《 运行错误 》 在程序的运行过程中产生的错误。. 二、 Java 对异常的处理机制. Java 使用异常对 Java 程序给出一个统一和相对简单的 抛出 和 处理 错误的机制。如果一个方法本身能抛出异常,当所调用的方法出现异常时,调用者可以 捕获 异常使之得到处理;也可以 回避 异常,这时异常将在调用的堆栈中向下传递,直到被处理。. b. a. c. d. 必须解决. - PowerPoint PPT PresentationTRANSCRIPT
第 8 章
异 常处理异 常处理
一、程序中的错误 《编译错误》 由于所编写的程序存在语法问题,未能
通过由源代码到目标代码的编译过程而产生的错误。它将由语言的编译系统负责检测和报告。
《运行错误》 在程序的运行过程中产生的错误。
二、 Java 对异常的处理机制 Java 使用异常对 Java 程序给出一个统一
和相对简单的抛出和处理错误的机制。如果一个方法本身能抛出异常,当所调用的方法出现异常时,调用者可以捕获异常使之得到处理;也可以回避异常,这时异常将在调用的堆栈中向下传递,直到被处理。
发现异常自行处理
必须解决 自行解决或将其抛出。
发现异常不自行解决,将其抛出。
a b c d
异常类
Error 类对象由 Java 虚拟机生成并抛出;Exception 类对象由应用程序处理或抛出。Throwable 类是类库 java.lang 包中的一个类
Object
Throwable
Error Exception
AWTException IOException RuntimeException
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 、抛出异常 在有些情况下,一个方法并不需要处理它
所生成的异常,而是向上传递,由调用它的方法来处理这些异常,这时就要用到 th
row 子句。其格式如下:返回类型 方法名( [ 参数表 ] ) 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{ // 自定义的异常类子类 MyExceptionpublic 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.ge
tEmpName()+" 非法变动工资变化: "+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()).doub
leValue();• 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,in
itsal));• m_EmpSalary=initsal;• }• public String getEmpName(){• return m_EmpName;• }• public double getEmpSalary(){• return m_EmpSalary;• }
• public boolean setEmpSalary(double newsal)• throws IllegalSalaryException,IllegalSalaryChangeExce
ption• {• if(newsal<800)• throw(new IllegalSalaryException(this,newsa
l));• 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;• }• }