异常指程序运行过程中出现的非正常现象。
9.1 java异常处理机制
在Java中,将异常情况分为Exception(异常)和Error(错误)两大类。 Error 类对象由 Java 虚拟机生成并抛出;Exception 类对象由应用程序处理或抛出
异常类的继承结构
其中Exception和Error又包含许多子类,exception子类的继承关系
Exception
ClassNotFoundException
ClassNotSupportedException
IllegalAccessException
InstantiationException
InterruptedException
NoSuchMethodException
RuntimeException
ArithmeticException
ArrayStoreException
ClassCastException
IllegalArgumentException
IllegalThreadStateException
NumberFormatException
IllegalMonitorStateException
IndexOutOfBoundsException
ArrayIndexOutOfBoundsException
StringIndexOutOfBoundsException
NegativeArraySizeException
NullPointerException
SecurityException
Exception 类的主要方法
public Exception( );
public Exception(String s);
public String toString( );
public String getMessage( );
9.2 异常处理方式
9.2.1 try…catch…finally结构
在Java中,可以通过try…catch…finally结构对异常进行捕获和处理,其形式如下:
try
{
可能出现异常的程序代码
}
catch (异常类名1 异常对象名1)
{ 异常类名1对应的异常处理代码 }
catch (异常类名2 异常对象名2)
{ 异常类名2对应的异常处理代码 }
┇
[ finally
{ 必须执行的代码 } ]
说明:
1.将可能发生异常的程序代码放置在try程序块中。程序运行过程中,如果该块内的代码没有出现任何异常,后面的各catch块不起任何作用。
但如果该块内的代码出现了异常,系统将终止try块代码的执行,自动跳转到所发生的异常类对应的catch块中,执行该块中的代码。
2. 其中的finally块是个可选项,如果含有finally块,无论异常是否发生,finally块的代码必定执行。
3.一个try块可以对应多个catch块,用于对多个异常类进行捕获。但如果它们之间有父子关系,应该将子类的catch块放置在父类catch块之前。
例9-1 捕获数组下越界异常
package example9_1; public class Exception1 { public static void main(String args[]) { try { int a[] = { 1, 2, 3, 4, 5 }, sum = 0; for (int i = 0; i <= 5; i++) sum = sum + a[i]; System.out.println("sum=" + sum); System.out.println("Successfully! "); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("ArrayIndexOutOfBoundsException detected"); } finally { System.out.println(" Programm Finished! "); } } }
运行结果为:
arrayindexoutofboundexception detected
program finished!
如果将循环语句中的i<=5改为i<5,那么不会产生异常try块内的所有语句正常执行,但catch块将不执行,最后跳到finally块去执行。
例9-2 捕获算术异常
package example9_2; public class Exception2 { public static void main(String args[]) { try { int x, y; x = 15; y = 0; System.out.println(x / y); System.out.println("Computing successfully!"); } catch (ArithmeticException e) { System.out.println(" ArithmeticException catched !"); System.out.println("Exception message:" + e.toString()); } finally { System.out.println("Finally block!"); } } }
运行结果为
ArithmeticException catched!
Exception message:java.lang.ArithmeticException:/by zero
Finally block!
9.2.2 抛出异常
通常情况下,异常是由系统自动捕获的。但程序员也可以自己通过throw语句抛出异常。throw语句的格式为:
throw new 异常类名(信息)
其中异常类名为系统异常类名或用户自定义的异常类名,“信息”是可选信息。如果提供了该信息,toString()方法的返回值中将增加该信息内容
package example9_3; public class Exception3 { public static int Sum(int n) { if (n < 0) throw new IllegalArgumentException("n应该为正整数!"); int s = 0; for (int i = 0; i <= n; i++) s = s + i; return s; } public static void main(String args[]) { try { int n = Integer.parseInt(args[0]); System.out.println(Sum(n)); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("命令行为:" + "java Exception3 <number>"); } catch (NumberFormatException e2) { System.out.println("参数<number>应为整数!"); } catch (IllegalArgumentException e3) { System.out.println("错误参数:" + e3.toString()); } finally { System.out.println("程序结束!"); } } }
如果运行该程序的命令输入为java Exception3
屏幕显示为:
命令行为:java exception 3 <number>
程序结束!
如果运行该程序的命令行输入为:java exception3 –4
屏幕显示 为:
错误参数:java.lang.IllegalArgumentException:n应该为正整数!
程序结束!
2.抛出异常选项
在一些情况下,一个方法并不需要处理它所生成的异常,而是向上传递,由调用该方法的其他方法来捕获该异常,这时就要用到throws子句。
使用格式如下:
返回值类型名 方法名([参数表]) throws 异常类型名
{
声明部分
语句部分
}
例9-4 抛出异常的方法
public class Exception4 { public static int Sum() throws NegativeArraySizeException { int s = 0; int x[] = new int[-4]; for (int i = 0; i < 4; i++) { x[i] = i; s = s + x[i]; } return s; } public static void main(String args[]) { try { System.out.println(Sum()); } catch (NegativeArraySizeException e) { System.out.println("异常信息:" + e.toString()); } } }
解析:在方法sum()中,初始化数组x时使用了int[-4],将触发NegativeArray-SizeException异常,但sum()方法不对该异常捕获和处理,而希望调用它的
方法对该异常捕获和处理,所以在声明方法时,在头部增加了“throws NegativeArraySzieException”选项,以抛出异常。
9.2.3 自定义异常类
在程序设计过程中,会出现各种各校的问题 有些可以通过java系统提供的异常来处理,但还有一引坏能通过java系统的已有类解决。在此情况下,可以自
已定义异常类来处理。
例9-5 自定义异常
package example9_5; public class OverFlowException extends Exception { OverFlowException() { System.out.println("此处数据有溢出,溢出类是OverFlowException"); } }
package example9_5; public class Exception5 { public static int x=100000; public static int multi() throws OverFlowException { int aim; aim=x*x*x; if(aim>1.0E8 || aim<0) { throw new OverFlowException(); } else return x*x; } public static void main(String args[]) { int y; try { y= multi(); System.out.println("y="+y); } catch(OverFlowException e) { System.out.println(e); } } }
解释:OVERFlowException 是一个自定义的异常类,其中寂静义了构造方法,其功能是输出信息:此处数据有溢出,溢出类是overflowexception
该程序的运行结果如下:
些数据有溢出,溢出类是overFlowException
OverFlowException
例9-6 处理多种异常
package example9_6; public class MathException extends Exception{ MathException() { System.out.println("输入数据不正确"); } }
package example9_6;
import javax.swing.JOptionPane;
public class Exception6 {
public static String name;
public static int pay;
public static void inputdata() throws MathException
{
try
{
name=JOptionPane.showInputDialog("请输入您的姓名");
if(name.equals("")) throw new Exception();
//假如没有输入名字就"抛出"一个Exception异常
pay=Integer.parseInt(JOptionPane.showInputDialog("请输入您的月工资"));
if(pay<0) throw new MathException();
//假如输入的月工资数小于零,就会"抛出"自定义异常mathException
}
catch(Exception e) //捕获Exception异常
{
System.out.println(e);
System.exit(0);
}
}
public static void main(String args[])
{
try
{
for(int i=1;;i++) //没有给出循环次数限制
{
inputdata();
System.out.println(name+"的年薪是"+pay*12);
}
}
catch(MathException pt) //捕获自定义异常
{
System.out.println(pt);
System.exit(0);
}
}
运行程序时,如果为姓名输入一个空串,系统显示:
java.lang.Exception
如果为姓名输入”zhang”,接着为工资输入”-500”,系统显示:
输入数据不正确
mathexception
如果为姓名输入”zhang”,接着为工资输入”300”,系统显示:
zhang的年薪是3600