一、什么是异常
简单地讲,异常就是程序出现了不正常的状况。
二、异常的分类
Throwable:是 Java 语言中所有错误或异常的超类。其包含两个子类:Error和Exception。
Error : 错误,用于指示合理的应用程序不应该试图捕获的严重问题,比如OutOfMemoryError(内存溢出)、IOError等。我们一般不对Error做处理,因为我们处理不了,一旦发生错误,jvm将会终止程序。
Exception:异常。一般来说常见的异常分为RutimeException(运行时期异常)和非RutimeException(编译时期异常)。
RutimeException(运行时期异常): 在程序运行过程中出现的异常,一般来说我们不做异常处理。这类异常出现的原因通常是因为我们写的代码不够严谨造成的,因此当我们的程序出现运行时期异常时,我们要做的就是修改代码,保证代码的严谨性和健壮性。
下面的代码就会出现运行时期异常(ArithmeticException):
int a = 2;
int b = 0;
System.out.println(a / b);
非RutimeException(编译时期异常) :在编译时期出现的异常,出现这种异常时,我们的代码是无法通过编译的。因此,这类异常我们必须进行处理。记住,除了
RutimeException及其子类的其他异常都可视为编译时期异常。
运行时期异常和编译时期异常的区别:
运行时期异常:代码可以通过编译,我们可以进行显式的异常处理,也可以不进行处理。
编译时期异常: 代码无法通过编译,我们必须进行显式的异常处理。
三、异常的处理
前面我们已经提过了,Error 和RutimeException我们不需要对其作出处理,我们需要做处理的只有编译时期异常。为什么我们要进行异常处理呢?
首先,如果不处理异常,代码将无法通过编译,也就更不用说执行了。其次,jvm会进行默认的异常处理,但是一旦jvm进行异常处理,当异常出现时,程序就运行终止,后 续代码也就无法执行了。
示例代码: <pre name="code" class="java">import java.io.File;
public class ExceptionDemo {
public static void main(String[] args) {
File file = new File("d:"+File.separator+"test.txt");
if (!file.exists())
file.createNewFile();
}
}
<pre name="code" class="java">import java.io.File;
public class ExceptionDemo {
public static void main(String[] args) {
File file = new File("d:"+File.separator+"test.txt");
if (!file.exists())
file.createNewFile();
}
}
(一)通过 try...catch...finally... 进行处理
1.
try...catch...finally... 的常见形式:
第一种:
try{
可能出现问题的代码;
}catch( 异常类名 异常对象){
需要做的处理;
}finally{
一定要执行的代码;
}
try{
可能出现问题的代码;
}catch( 异常类名 异常对象){
需要做的处理;
}
第三种:
try{
可能出现问题的代码;
}catch( 异常类名1 异常对象1){
需要做的处理;
}catch( 异常类名2 异常对象2){
第四种:
需要做的处理;
}
......
try{
可能出现问题的代码;
}catch( 异常类名1 异常对象1){
需要做的处理;
}catch( 异常类名2 异常对象2){
需要做的处理;
}finally{
一定要执行的代码;
}
注意:在实行多个catch语句进行异常处理时,应该注意同级别的异常谁前谁后无所谓;如果不同级别的异常,应该将级别低的异常类往前放,级别高的往后放。如果把级别高的异常放前面,就会出现错误。
第五种:
try{
可能出现问题的代码;
}finally{
一定要执行的代码;
}
第六种:
try{
可能出现问题的代码;
}catch( 异常类名1 | 异常类名2 异常对象){
需要做的处理;
}
第七种:
try{
可能出现问题的代码;
}catch( 异常类名1 | 异常类名2 异常对象){
需要做的处理;
}finally{
一定执行的代码;
}
注意:
上面的第六、七中格式,是在jdk7中开始出现的。因此只有在jdk7之后才能使用。尽管相对于第三种格式,简化了不少,但存在了一定的弊端:对不同的异常做得是相同的处理;用|分隔的异常类必须是同级别的。比如,下面代码就会出现问题,原因是
IllegalClassFormatException和SQLTransientException不是同级别的异常。try{
代码
;
}catch(IllegalClassFormatException|SQLTransientException e){
处理;
}
以上就是try...catch...finally... 的常见形式。我们需要根据不同的场景选择不同的形式。在使用
try...catch...finally...进行异常处理时,我们还需要注意一下几点:
第一、try 里面的代码越少,越好。尽量精确的找出哪些代码才是真正可能出现问题的代码。
第二、catch里面的异常类名的级别越底越好,也就是说,异常给的越明确越好;另外,对异常的处理必须有内容,哪怕只是一句简单的提示打印语句,当然,没有内容也不会报错。
第三、finally 中的代码一定会被执行,除非在执行finally之前,jvm已经停止运行了,比如 System.exit(0);
根据上面的介绍,可以对示例代码做以下处理了:
import java.io.File; import java.io.IOException; public class ExceptionDemo { public static void main(String[] args) { File file = new File("d:"+File.separator+"test.txt"); if (!file.exists()) try { file.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
(二)throws
1. 当一个异常我们没有权限处理,或者根本就处理不了,那么我们就不处理了,而是将异常抛给调用者去处理,这时就用到了throws。
它的目的就是告诉程序员,如果调用这个方法可能会出现问题,你可能需要处理这个问题。
2.用法:
第一种:一个异常 :方法名( )throws 异常类名{}
举例: public void xxx()throws IOException{ }
第二种:多个异常:方法名( )throws 异常类名1,异常类名2{}
举例: public void xxx()throws IOException,...{ }