第 4 章 异常北京大学计算机系代亚非
2第 4章 异常
4.1 异常的概念
4.2 异常的分类
4.3 捕获异常
4.4 声明异常
4.5 抛出异常
4.6 创造自己的异常
4.7 总结
34.1 异常的概念
什么是异常?
异常实际上是程序中错误导致中断了正常的指令流的一种事件,
没有处理错误的程序,
read-file {
openTheFile;
determine its size;
allocate that much memory;
closeTheFile;
}
44.1 异常的概念
以常规方法处理错误
openFiles;
if (theFilesOpen) {
determine the lenth of the file;
if (gotTheFileLength){
allocate that much memory;
if (gotEnoughMemory) {
read the file into memory;
if (readFailed) errorCode=-1;
else errorCode=-2;
}else errorCode=-3;
}else errorCode=-4 ;
}else errorCode=-5;
54.1 异常的概念
观察前面的程序你会发现大部分精力花在出错处理上了,
只把能够想到的错误考虑到,对以外的情况无法处理
程序可读性差
出错返回信息量太少
64.1 异常的概念
用异常的形式处理错误
read-File;
{ try {
openTheFile;
determine its size;
allocate that much memory;
closeTheFile;
}catch(fileopenFailed) { dosomething; }
catch(sizeDetermineFailed) {dosomething;}
catch(memoryAllocateFailed){ dosomething;}
catch(readFailed){ dosomething;}
catch(fileCloseFailed) { dosomething; }
}
74.1 异常的概念
和传统的方法比较异常的优点,
1.把错误代码从常规代码中分离出来
2,把错误传播给调用堆栈
3,按错误类型和错误差别分组
4,系统提供了对于一些无法预测的错误的捕获和处理
5,克服了传统方法的错误信息有限的问题
method1
method2
method3
method4 产生异常传递 处理异常
84.1 异常的概念
,class ExcepTest{ public void main(String args[])
{ int b=0; int a;
try { a=4/b;}
catch(ArithmeticException e)
{ System.out.println(“divided by 0”);} }}
try{ URL url=new
URL(http://www.hit.edu.cn/”,”hit.gif”);}
catch(MalformedURLEception e)
{ badURL=true; repaint();}
94.2 异常的分类
异常是一个对象,它继承自 Throwable类,所有的
Throwable类的子孙类所产生的对象都是例外,
Error:由 Java虚拟机生成并抛出,Java程序不做处理,
Runtime Exception(被 0除等系统错误,数组下标超范围 ):由系统检测,用户的 Java 程序可不做处理,系统将它们交给缺省的异常处理程序,
Exception(程序中的问题,可预知的 ),Java编译器要求 Java程序必须捕获或声明所有的非运行时异常
throw:用户自己产生异常
104.2 异常的分类
,Throwable
Error
Exception
RuntimeException
缺省的异常处理程序由用户捕获或声明并处理不做处理用户自己产生的异常要处理
114.3 捕获异常
捕获并处理异常
try {
//接受监视的程序块,在此区域内发生
//的异常,由 catch中指定的程序处理 ;
}catch(要处理的异常种类和标识符 ) {
//处理异常 ;
}catch(要处理的异常种类和标识符 ) {
//处理异常 ;
}
124.3 捕获异常
常见的异常
ArithmeticException
ArrayIndexOutOfBandsException
ArrayStoreException
IOException
FileNotFoundException
NullPointerException
MalformedURLException
NumberFormatException
OutOfMemoryException
如果在使用能够产生异常的方法而没有捕获和处理,将不能通过编译
134.3 捕获异常
例,编写 Java程序,包含三种异常
算术异常,字符串越界,数组越界
观察输出信息,
每个异常对象可以直接给出信息
144.3 捕获异常class first_exception
{ public static void main(String args[])
{ char c; int a,b=0;int[] array=new int[7];
String s="Hello";
try {a=1/b;}
catch(ArithmeticException ae)
{ System.out.println(“Catch,+ae));}
try {array[8]=0;}
catch(ArrayIndexOutOfBoundsException ai)
{ System.out.println((“Catch,+ai);}
try{ c=s.charAt(8));}
catch(StringIndexOutOfBoundsException se)
{ System.out.println((“Catch,+se);}}}
154.3 捕获异常
一定会执行的程序块 ---finally
异常处理的统一出口
try {
//常规的代码 ;
}
catch()
{ //处理异常 }
finally {
//不论发生什么异常 (或者不发生任何异常 ),都要执行的部分 ;
}
164.3 捕获异常
finally在文件处理时非常有用
try {
对文件进行处理的程序 ;
}catch(IOException e) {
//对文件异常进行处理 ;
}finally {
不论是否发生异常,都关闭文件 ;
}
174.4 声明异常
一个方法不处理它产生的异常,而是沿着调用层次向上传递,由调用它的方法来处理这些异常,叫声明异常,
声明异常的方法
在产生异常的方法名后面加上要抛出 (throws)的异常的列表
void compute(int x)throws
ArithmeticException {… }
returnType methodName([parameterlist])
throws exceptionList
184.4 声明异常例,若因某种原因不想在创建
URL的方法中处理异常
public method1()
{ int x;
try { x=System.in.read();
compute(x);}
catch(IOException ioe)
{ System.out.println(“read error”); }
catch(ArithmeticException e)
{ System.out.println(“devided by 0”); }
}
public int compute(int x) throws
ArithmeticException e)
{ return z=100/x;}
194.4 声明异常
method1
computer 异常抛出处理
204.4 声明异常例,说出程序执行结果
public class exception1
{ void Proc(int sel) throws
ArithmeticException,
ArrayIndexOutOfBoundsException
{ System.out.println(“In Situation" + sel );
if (sel==0) {
System.out.println("no Exception caught");
return;
}else if(sel==1) {int iArray[]=new int[4];
iArray[10]=3;
}
}
214.4 声明异常
public static void main(String args[])
{ try { Proc(0);
Proc(1);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("Catch"+e);
}
}
c:>jview throwsException
In Situation 0
no Exception caught
In Situation 1
Catch
java.lang.ArrayIndexOutOfBoundsException:10
224.5 抛出异常
抛弃异常,不是出错产生,而是人为地抛出
throw ThrowableObject;
throw new ArithmeticException();
例,编写程序人为抛出 (JavaThrow.prj)
ArithmeticException,
ArrayIndexOutOfBoundsException
StringIndexOutOfBoundsException
A method Exception Another method
throw caught
234.5 抛出异常
class JavaThrow
{ public static void main(String args[])
{ try{ throw new ArithmeticException();}
catch(ArithmeticException ae)
{ System.out.println(ae); }
try{ throw new
ArrayIndexOutOfBoundsException();}
catch(ArrayIndexOutOfBoundsException ai)
{ System.out.println(ai); }
try { throw new
StringIndexOutOfBoundsException();}
catch(StringIndexOutOfBoundsException si){
{ System.out.println(si); }
244.6 创造自己的异常
不是由 Java系统监测到的异常 (下标越界,被
0-除等 ),而是由用户自己定义的异常,
用户定义的异常同样要用 try--catch捕获,但必须由用户自己抛出 throw new
MyException.
异常是一个类,用户定义的异常必须继承自
Throwable或 Exception类,建议用
Exception类,
254.6 创造自己的异常
形如,
class MyException extends Exception
{….};
例 1,计算两个数之和,当任意一个数超出范围时,
抛出自己的异常
public class NumberRangeException extends
Exception
{ public NumberRangeException(String msg)
{ super(msg); }
}
264.6 创造自己的异常
,public boolean action(Event evt,Object arg)
{ try {
int answer = CalcAnswer();
answerStr = String.valueOf(answer);
}catch (NumberRangeException e)
{ answerStr = e.getMessage(); }
repaint();
return true;
}
274.6 创造自己的异常
,
public int CalcAnswer() throws NumberRangeException
{ int int1,int2; int answer = -1;
String str1 = textField1.getText();
String str2 = textField2.getText();
try { int1 = Integer.parseInt(str1);
int2 = Integer.parseInt(str2);
if ((int1 < 10) || (int1 > 20) ||
(int2 < 10) || (int2 > 20))
{ NumberRangeException e =
new NumberRangeException
(”Numbers not within the specified range.");
throw e;
}
answer = int1 + int2;
}catch (NumberFormatException e)
{ answerStr = e.toString(); }
return answer;
}
284.6 创造自己的异常
例 2,在定义银行类时,若取钱数大于余额则作为异常处理
(InsufficientFundsException).
思路,产生异常的条件是余额少于取额,因此是否抛出异常要判断条件
取钱是 withdrawal方法中定义的动作,因此在该方法中产生异常,
处理异常安排在调用 withdrawal的时候,
因此 withdrawal方法要声明异常,由上级方法调用
要定义好自己的异常类
294.6 创造自己的异常
,
class Bank
{ double balance;
public void deposite(double dAmount)
{ if(dAmount>0.0) {balance+=dAmount;}}
public void withdrawal(double dAmount)
throws InsufficientFundsException
{ if (balance<dAmout) {
throw new InsufficientFundsException(this,dAmount);
}
balance=balance-dAmount;
}
public void show_balance()
{ System.out.println("The balance is "+(int)balance);}
}
304.6 创造自己的异常
public class ExceptionDemo
{ public static void main(String args[])
{ try
{ Bank ba=new Bank(50);
ba.withdrawal(100);
System.out.println(“Withdrawal successful!”);
}catch(Exception e)
{ System.out.println(e.toString()); }
}
314.6 创造自己的异常
,public class InsufficientFundsException extends Exception
{ private Bank excepbank;
private double excepAmount;
InsufficientFundsException(Bank ba,double dAmount)
{ excepbank=ba;
excepAmount=dAmount;
}
public String excepMesagge()
{ String str=“The balance”+ excepbank.showBalance()+
“The withdrawal was”+excepAmount;
return str; }
324.7 小结
1.一般格式,正常程序和出错处理分离开来
try { Java statement;
}catche(ExceptionType1 ExceptionObject) {
Exception1 handling;
} catche(ExceptionType2 ExceptionObject) {
Exception2 handling;
}….
}finally {
final handling;
// (统一的出口,最终必定要执行 )
}}
334.4 小结
2.把异常传播给堆栈,沿着被调用的顺序往前寻找,只要找到符合该异常种类彻底异常处理程序,就交给这部分程序去处理
Method1 Method2 Method3 Read-filecall call call
Try catch
产生异常
throwsthrowsthrows
344.4 小结
3.异常可以人为地抛出,用 throw new 语句
4.异常可以是系统已经定义好的,也可以是用户自己定义的
5,用户自己定义的异常一定继承自
Throwable或 Exception类
35作业
当用户按,T”或,t”时,人为抛出一个算术异常,处理 方式为打印出错信息
36
import java.awt.*; import java.applet.*;
public class keyException extends Applet
{ final int LOWERCASE_T = 116;
final int UPPERCASE_T = 84;
String str; int count=0;
public void paint(Graphics g)
{ g.drawString(" "+str+count,5,20); }
public boolean keyDown(Event evt,int key)
{if ((key == LOWERCASE_T) || (key == UPPERCASE_T))
{ try{ throw new ArithmeticException();}
catch(ArithmeticException e)
{ count++; str=e.toString(); repaint();}
return true; } return false; }