基本概念
当出现程序无法控制的外部环境问题(文件不存在、网络不可用等)时,Java就会用异常对象来描述。、
Java中用两种方法处理异常
- 在发生异常的地方直接处理。
- 将异常抛给调用者,让调用者处理。
异常分类
- 检查性异常:java.lang.Exception(程序在编译的时候就能后探测你这个地方可能有异常)
- 运行期异常:java.lang.RuntimeException(编译器发现不了的,只有运行的时候才发现的,比如数组越界访问,一般是逻辑错误)
- 错误:java.lang.Error
顶层是java.lang.Throwable类,检查性异常、运行期异常、错误异常都是这个类的子孙类。
- java.lang.Exception、java.lang.Error继承自java.lang.Throwable
- java.lang.RuntimeException继承自java.lang.Exception
检查性异常
程序正确,但因为外在的环境条件不满足引发,例如:用户错误及I/O问题——程序错误打开一个并不存在的远程Socket端口,或者是打开不存都在的文件时,这不是程序本身的逻辑错误,而很可能是远程机器名字错误(用户拼写错误),对商用软件来说,必须考虑并且处理这个问题,Java编译器强制要求处理这类异常,如果不捕获这类异常,程序就不能被编译。
FileReader fr = new FileReader("/a.txt");
//当单独写上面这句话的时候,编译器很聪明,会知道这里可能会有异常,下面这句也一样!让你必须修改之后才可以编译通过
Socket s = new Socket("www.baidu.com",77);
运行期异常
意味着程序出现bug,如数组越界,0被整除,入参不满足规范……这类异常需要修改程序来避免,jav编译器强制要求处理这类异常。
比如:
int a = 4/0;
报错内容:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at sort.Sort.main(Sort.java:12)
再比如数组越界:
int arr[] = {1,2};
int c = arr[2];
报错内容:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at sort.Sort.main(Sort.java:15)
错误异常
一般很少见,也很难通过程序来解决,可能源于程序的bug,但一般更可能源于环境问题,如内存耗尽,错误在程序中无需处理,而由运行环境处理。
比如排序中,由于数据量太大,内存不够用。
异常处理
- try……catch
程序运行产生异常时,将从异常发生点中断程序并向外抛出异常信息。捕获到异常之后就不会再接着运行程序了。
try {
FileReader fr = new FileReader("/a.txt");
} catch (Exception e) {
e.printStackTrace();//这行的作用是把异常的信息输出,利于排除bug,如果不输出这行,则之后会不知道这里出错。
}
// 当单独写上面这句话的时候,编译器很聪明,会知道这里可能会有异常,下面这句也一样!
try {
Socket s = new Socket("www.baidu.com",77);
System.out.println("如果上一句话抛出异常,就不会看到这句话了");
} catch (Exception e) {
e.printStackTrace();
- finally
如果把finally块置try……catch……语句后,finally块一般都会得到执行,它相当于一个万能的保险,即使前面的try块发生异常而又没有对应异常的catch块,finally块将马上执行。
以下情形,finally块将不会被执行:
- finally块中发生了异常
- 程序所在线程死亡
- 在前面的代码中用了System.exit();
- 关闭CPU
还有一点,就是try……catch……finally不一定要三个一起用,可以没有finally,也可以没有catch。
FileReader fr = null;
try {
fr = new FileReader("a.txt"); //1
Socket s = new Socket("www.baidu.com",77);//2
//假如1没出错,但是2出错了,这里文件就处于一直打开的状态了,这个很可怕!!不关闭的话就会产生数据丢失!
} catch (Exception e) {
e.printStackTrace();
}finally{
//这个语句块一般都会被执行,不管有没有异常
//比如把要关闭的资源(文件、链接、内存……)关闭
if(fr != null){
try {
fr.close();
} catch (Exception e2) {
// TODO: handle exception
}
}
}
throws
就是将异常抛出,由调用的对象来处理。
class Father{
private Son son;
public void test(){
try {
son.test();//这句必须要处理异常,进行处理或者抛出。
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Son{
public void test() throws FileNotFoundException{
FileReader fr = new FileReader("a.txt");
}
}