Java中的异常处理机制是Java程序设计中非常重要的一个特性,它允许程序在出现错误或意外情况时进行适当的响应,而不是直接导致程序崩溃。异常处理遵循“捕获或者声明”原则,这意味着程序员要么捕获并处理可能发生的异常,要么声明方法可能抛出异常。
java使用异常对程序给出一个统一和相对简单的抛出和处理错误的机制。
如果一个方法本身能抛出异常,调用者可以捕获异常使之得到处理;
也可以回避异常,这时异常将在调用的堆栈中向下传递,直到被处理。
一类是非致命性的,通过某种修正后程序还能继续执行。这类错误称作异常。
另一类是致命性的,即程序遇到了非常严重的不正常状态,不能简单地恢复执行,这就是错误。、
检查型异常(Checked Exception): 这类异常在编译期间就会被检查,如果一个方法可能会抛出检查型异常,那么该方法必须使用 throws
关键字声明它可能抛出的异常类型,或者在方法内部捕获并处理这些异常。例如:IOException
、SQLException
等。
public void readFile() throws IOException {
File file = new File("file.txt");
FileReader fr = new FileReader(file);
// ...
}
运行时异常(Unchecked Exception): 这类异常不需要在方法签名中声明,通常是因为编程错误或者逻辑错误导致的,如空指针异常(NullPointerException)、数组越界异常(ArrayIndexOutOfBoundsException)等。虽然编译器不会强制要求处理这类异常,但良好的编程习惯建议在代码中适当处理这类异常。
public void processValue(int[] array, int index) {
try {
System.out.println(array[index]);
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
}
异常处理的方法有两种:
1.使用try…catch…finally结构对异常进行捕获和处理;
2.通过throws和throw抛出异常
Java使用 try-catch-finally
结构来处理异常
格式;
try
{
可能出现异常的程序代码
}
catch (异常类名1 异常对象名1)
{ 异常类名1对应的异常处理代码 }
catch (异常类名2 异常对象名2)
{ 异常类名2对应的异常处理代码 }
┇
[ finally
{ 必须执行的代码 } ]
在 try
块中放置可能出现异常的代码,当发生异常时,控制流立即跳转到与之匹配的 catch
块。如果异常没有被捕获,程序将终止,并打印堆栈跟踪信息。finally
块总是在 try
或者 catch
后面执行,用于资源清理工作,如关闭文件、数据库连接等。
将可能发生异常的程序代码放置在try程序块中。程序运行过程中,如果该块内的代码没有出现任何异常,后面的各catch块不起任何作用。但如果该块内的代码出现了异常,系统将终止try块代码的执行,自动跳转到所发生的异常类对应的catch块中,执行该块中的代码。
其中的finally块是个可选项,如果含有finally块,无论异常是否发生,finally块的代码必定执行。 一个try块可以对应多个catch块,用于对多个异常类进行捕获。
以下4种特殊情况下,finally块不会被执行:
在finally语句块中发生了异常;
在前面的代码中使用了System.exit()退出程序;
程序所在的线程死亡;
关闭CPU。
e.g.
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! ");
}
}
}
运行这段代码时,由于循环条件错误,程序会在遍历到第6个元素时抛出异常。此时,控制流会立即跳转到与之匹配的
catch
块,输出 "ArrayIndexOutOfBoundsException detected"。最后,无论是否发生异常,都会执行finally
块中的代码,输出 "Programm Finished!"。
一个try块可以对应多个catch块,用于对多个异常类进行捕获:
当匹配某一个catch块的时候,就直接进入到这个catch块里面,后面在再有catch块的话,它不做任何处理,全部忽略掉;
所有catch块必须从最具体到最一般的顺序排列,即多个catch块中的异常出现继承关系,父类异常catch块放在最下面;
通常情况下,异常是由系统自动捕获的。但程序员也可以自己通过throw语句抛出异常。
格式如下:
throw new 异常类名(信息)
异常类名 e=new 异常类名(信息);
throw e;
抛出异常选项
在有些情况下,一个方法并不需要处理它所生成的异常,而是向上传递,由调用该方法的其他方法来捕获该异常,这时就要用到throws子句。其格式如下:
返回值类型名 方法名([参数表]) throws 异常类型名
{
声明部分
语句部分
}
public void readAndProcessFile() throws FileNotFoundException, IOException {
// 方法体内的代码
}
e,g,实例
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());
}
}
}
代码定义了一个名为
Exception4
的类,其中包含两个方法:Sum()
和main(String args[])
。主要目的是演示如何抛出和捕获NegativeArraySizeException
异常。
方法
Sum()
:
- 定义为静态方法,返回一个整数。
- 使用
throws NegativeArraySizeException
声明此方法可能会抛出NegativeArraySizeException
异常。- 在该方法内部尝试创建一个大小为
-4
的数组,由于数组长度不能为负数,在创建时会抛出NegativeArraySizeException
异常。- 即使创建数组的语句会导致异常,后续代码仍尝试对这个不存在的数组进行初始化和求和操作,但实际在创建数组时程序就已经抛出了异常,并不会执行到这些语句。
main(String args[])
方法:
- 包含一个
try-catch
结构来捕获可能由Sum()
方法抛出的NegativeArraySizeException
异常。- 在
try
块中调用Sum()
方法并打印其返回值。- 当
Sum()
方法抛出异常时,控制流会立即跳转到相应的catch
块,这里输出了捕获到的异常信息。
自定义异常类可以通过继承Exception类来实现。其一般形式为:
class 自定义异常类名 extends Exception
{
异常类体;
}
class MyCustomException extends Exception {
public MyCustomException(String message) {
super(message);
}
}