7.异常
在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可用异常传播机制通过 Java 应用程序传输的任何问题的共性。
Throwable 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。
关于错误:错误分为语法错误、运行时错误和逻辑错误三类。
- 语法错误(编译错误): 指未按照 Java 语法规则书写代码而产生的错误。一般集成开发软件均能提示和标 注语法错误之处。
- 运行时错误(语义错误) 程序没有语法错误,但在运行时从外部获得不正确的数据从而导致的错误。如将11 位电话号码赋值给一个整型变量将超出其表示的数据范围而引发错误。 这类错误一般会导致程序异常终止。
- 逻辑错误逻辑错误是人为导致的错误,表现为程序运行结果与预期不符。
参考:链接1
1.异常的类型
Java中不是所有的异常都必须进行处理,但检查异常必须进行处理。检查异常继承Exceotion。常见的检查异常有访问数据库时发生的SQLException、读写文件时发生的IOException。
2.异常的处理
- try语句体中是可能发生异常的代码,catch中声明捕捉异常的类型,并进行处理。
- 有try语句时,catch和finally只出现一个就行。
- 使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。
try/catch代码块中的代码称为保护代码,使用 try/catch 的语法如下:
try
{
// 程序代码
}catch(ExceptionName e1)
{
//Catch 块
}
- 实例
下面的例子中声明有两个元素的一个数组,当代码试图访问数组的第四个元素的时候就会抛出一个异常。
//ExcepTest.java 文件代码:
// 文件名 : ExcepTest.java
import java.io.*;
public class ExcepTest{
public static void main(String args[]){
try{
int a[] = new int[2];
System.out.println("Access element three :" + a[3]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("Exception thrown :" + e);
}
System.out.println("Out of the block");
}
}
以上代码编译运行输出结果如下:
Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3
Out of the block
5. 多重捕获块
一个 try 代码块后面跟随多个 catch 代码块的情况就叫多重捕获。
多重捕获块的语法如下所示:
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型3 异常的变量名3){
// 程序代码
}
3.finally关键字
finally 关键字用来创建在 try 代码块后面执行的代码块。
无论是否发生异常,finally 代码块中的代码总会被执行。 在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
- try catch finally结构
try发生异常->程序异常->有异常处理->程序正常,否则程序异常。
catch后到finally执行finally语句->程序正常,执行finally后面的语句,否则不执行。 - try finally结构
try异常->程序异常->执行finally语句。
程序一直异常未被处理,finally后面的语句不执行。
例如:
public class App_4 {
public static void main(String[] args) {
try{
int a = 2/0;
System.out.println("1 in try");
}catch(Exception e){
System.out.println("2 in catch");
}finally{
System.out.println("3 in finally");
}
System.out.println("4 after finally");
}
}
以上实例编译运行结果如下:
2 in catch
3 in finally
4 after finally
- finally 代码块出现在 catch 代码块最后,语法如下:
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
实例
ExcepTest.java 文件代码:
public class ExcepTest{
public static void main(String args[]){
int a[] = new int[2];
try{
System.out.println("Access element three :" + a[3]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("Exception thrown :" + e);
}
finally{
a[0] = 6;
System.out.println("First element value: " +a[0]);
System.out.println("The finally statement is executed");
}
}
}
以上实例编译运行结果如下:
Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3
First element value: 6
The finally statement is executed
注:
catch 不能独立于 try 存在。
在 try/catch 后面添加 finally 块并非强制性要求的。
try 代码后不能既没 catch 块也没 finally 块。
try, catch, finally 块之间不能添加任何代码。
4.throw/throws
4.1 throw/throws区别
结论:
使用的位置不同:throw是写在方法体里面。throws则是用在方法头上面。
作用不同:throw就是直接抛出一个异常,而throws则是说我这个方法可能会抛出一个异常。
自我建议:
尽量少使用,可能发生异常的语句就放在try,catch语句块中,直接进行处理(要处理,哪怕是写一个输出语句)。使用throw也是主动抛出异常,调用这个方法的上级就需要处理这个异常。
如果在代码块中使用了throw的话,最好也配套在方法头上面加上throws,好直接告诉上层这个异常的类型。
如果发生IO异常,一定要finally里面关闭输入出流。
参考链接
如果一个方法没有捕获到一个检查性异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。
4.2 例1
例如,下面的方法声明抛出 RemoteException 和 InsufficientFundsException:
import java.io.*;
public class className
{
public void withdraw(double amount) throws RemoteException,
InsufficientFundsException
{
// Method implementation
}
//Remainder of class definition
}
4.3 例2
import java.io.*;
public class App_5 {
public static void main(String[] args) throws IOException{
FileReader fr = new FileReader("io.txt");
}
}
io.txt文件不一定存在,不存在就会发生IOException异常。如果没有throws声明,由于IOException是检查异常,编译提示错误。(有不也报错么…?
5.自定义异常
1.首先确定继承的类的类型,用户必须进行异常处理的继承Exception,不要求用户处理的可以继承RuntimeException。
2.自定义异常的类命名时习惯性用Exception处理。