异常¶
异常体系¶
- 程序出现的不正常的情况.
- 异常的体系
- Throwable
- |–Error 严重问题, 我们不处理.
- |–Exception
- |–RuntimeException 运行期异常, 我们需要修正代码
- |–非RuntimeException 编译期异常, 必须处理的, 否则程序编译不通过
- Throwable
内置异常¶
异常处理¶
- JVM的默认处理
- 把异常的名称,原因,位置等信息输出在控制台, 但是呢程序不能继续执行了.
- 自己处理
- a:try…catch…finally
- 自己编写处理代码,后面的程序可以继续执行
- b:throws
- 把自己处理不了的, 在方法上声明, 告诉调用者, 这里有问题
- a:try…catch…finally
捕获异常¶
使用 try
和 catch
关键字可以捕获异常. try/catch
代码块放在异常可能发生的地方. try/catch代码块中的代码称为保护代码, 使用
try/catch 的语法如下:
try
{
// 程序代码
}catch(ExceptionName e1)
{
//catch 块
}
catch
语句包含要捕获异常类型的声明. 当保护代码块中发生一个异常时,
try 后面的 catch 块就会被检查.
如果发生的异常包含在 catch 块中, 异常会被传递到该 catch 块, 这和传递一个参数到方法是一样.
实例
下面的例子中声明有两个元素的一个数组, 当代码试图访问数组的第三个元素的时候就会抛出一个异常.
// 文件名 : 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");
}
}
多重捕获块¶
一个 try 代码块后面跟随多个 catch 代码块的情况就叫多重捕获.
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}
上面的代码段包含了 3 个 catch块.
可以在 try 语句后面添加任意数量的 catch 块.
如果保护代码中发生异常, 异常被抛给第一个 catch 块.
如果抛出异常的数据类型与 ExceptionType1 匹配, 它在这里就会被捕获.
如果不匹配, 它会被传递给第二个 catch 块.
如此, 直到异常被捕获或者通过所有的 catch 块.
实例
try
{
file = new FileInputStream(fileName);
x = (byte) file.read();
}catch(IOException i)
{
i.printStackTrace();
return -1;
}catch(FileNotFoundException f) //Not valid!
{
f.printStackTrace();
return -1;
}
捕获方式¶
try...catch...finally
try...catch...
try...catch...catch...
try...catch...catch...fianlly
try...finally
throws/throw¶
throws
如果一个方法有捕获一个检查性异常, 那么该方法必须使用 throws 关键字来声明. throws 关键字放在方法签名的尾部.
- 在方法声明上,后面跟的是异常的类名,可以是多个
- throws是声明方法有异常, 是一种可能性, 这个异常并不一定会产生
throw
- 在方法体中, 后面跟异常对象名, 并且只能是一个
throw
触发异常, 无论它是新实例化的还是刚捕获到的.
下面方法的声明抛出一个 RemoteException
异常:
import java.io.*;
public class className
{
public void deposit(double amount) throws RemoteException
{
// Method implementation
throw new RemoteException();
}
//Remainder of class definition
}
一个方法可以声明抛出多个异常, 多个异常之间用逗号隔开.
例如, 下面的方法声明抛出 RemoteException
和
InsufficientFundsException
import java.io.*;
public class className
{
public void withdraw(double amount) throws RemoteException,
InsufficientFundsException
{
// Method implementation
}
//Remainder of class definition
}
finally¶
finally 关键字用来创建在 try 代码块后面执行的代码块.
无论是否发生异常, finally 代码块中的代码总会被执行, 以运行清理类型等收尾善后性质的语句. 特殊情况: 在执行到finally之前JVM退出了
finally 代码块出现在 catch 代码块最后
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
注意下面事项
- catch 不能独立于 try 存在.
- 在 try/catch 后面添加 finally 块并非强制性要求的.
- try 代码后不能既没 catch 块也没 finally 块.
- try, catch, finally 块之间不能添加任何代码.
自定义异常¶
在 Java 中你可以自定义异常. 编写自己的异常类时需要记住下面的几点.
- 所有异常都必须是 Throwable 的子类.
- 如果希望写一个检查性异常类, 则需要继承 Exception 类.
- 如果你想写一个运行时异常类, 那么需要继承 RuntimeException 类.
只需要提供无参构造和一个带参构造即可
可以像下面这样定义自己的异常类:
class MyException extends Exception{
}
只继承Exception 类来创建的异常类是检查性异常类.
下面的 InsufficientFundsException 类是用户定义的异常类, 它继承自 Exception.
一个异常类和其它任何类一样, 包含有变量和方法.
编译器异常和运行期异常¶
- 编译期异常 必须要处理的, 否则编译不通过
- 运行期异常 可以不处理, 也可以处理
异常注意事项¶
- 异常的注意实现
- 父的方法有异常抛出,子的重写方法在抛出异常的时候必须要小于等于父的异常
- 父的方法没有异常抛出,子的重写方法不能有异常抛出
- 父的方法抛出多个异常,子的重写方法必须比父少或者小