您的位置:首页 > 编程语言 > Java开发

Java异常处理机制

2017-02-28 14:58 190 查看
异常是 一个类class

java.lang.Exception

异常分为两种:

a) Checked exception (非 Runtime Exception) 非运行时异常

b) Unchecked exception(Runtime Exception) 运行时异常

异常的继承关系:

1. Java中所有的异常类都会直接或间接地继承自Exception。

2. RuntimeException类也是直接继承自 Exception类,它叫做运行时异常,Java中所有的运行时异常都会直接或间接地继承自 RuntimeException。

3. Java 中凡是继承自 Exception 而不是继承自 RuntimeException 的类都是非运行时异常。

异常常用的一个方法 printStackTrace() 打印这个异常的信息

异常是一个类,当程序捕获了一个异常时,会动态的为这个异常生成一个异常对象

异常处理的第一种方式:

异常处理的一般结构是: 下面是个普遍的结构,还有许多变形

try {

}

catch(Exception e) {

}

finally {

}

如果try块中没有出现异常,那么catch中的语句是不会被执行的

无论程序是否出现异常,finally 块中的代码都是会被执行的。 (有一些特殊情况不会被执行,在下面有详细的内容)

注意的变形的是:

1. try{} catch{} finally{} 是可以的

2. try{} catch(){ } 是可以的,

3. try{} finally{ } 编译没问题的,但是运行的时候相当于没有对异常进行处理,所以 finaaly快执行完之后,程序就终止了,后面的代码就不会再被执行,在下面的例子中意味着 这一句 System.out.println(“我最后输出”) 不会被执行了

4. try { } catch{} catch{}…. 一个try块可以跟着很多catch块,但是最终只有一个catch快会被执行 ,但是一个try快只能跟着一个finally块,不能有多个finally块。

一般来说finally 快都是会被执行的,但是有一些特殊情况除外:

在try 或者catch 块中出现了 system.exit(0)(正常终止), system.exit(1)(异常终止) 程序强制退出,则finally快不会被执行。需要谨记的一点, 在try 或者catch 块中出现了return 并不会影响finally快的执行,但是finally块之后的内容就不会被执行了。

try{
int a = 3;
int b = 0;
c = a / b;
System.out.println("我执行了吗?");  // 这一句没有被执行
}
catch(Exception e){
e.printStackTrace();  // 打印异常的信息
return;
}
finally{
System.out.println("我都会被执行");  // 都会被执行
}
System.out.println("我最后输出");   // 不会被执行


try语句没有被执行到,如在try语句之前return就返回了,这样finally语句就不会执行。这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到 。

多线程里面也会出现finally块不会被执行的情况:

@Override
public void run() {
// TODO Auto-generated method stub
try{
System.out.print("Starting ADaemon");
TimeUnit.MILLISECONDS.sleep(1);
}catch(InterruptedException e){
System.out.print("Exiting via InterruptedException");
}finally{
System.out.print("the finally really run?");
}
}


一个例子说明了异常的一些情况:

public class ExceptionTest {
public static void main(String[] args) {
int c = 0;
try{
int a = 3;
int b = 0;
c = a / b;  // 发生了异常,动态的生成一个异常对象,然后跳出 try 块,后面的不再执行
System.out.println("我执行了吗?");  // 这一句没有被执行
}catch(Exception e){
e.printStackTrace();  // 打印异常的信息
} finally{
System.out.println("我都会被执行");  // 都会被执行
}

System.out.println("我最后输出");  // 因为前面进行了异常处理,所以会执行

int a = 3;
int b = 0;
c = a / b;   //  发生了异常,但是没有对其进行处理,因此程序终止,下面的语句不再执行
System.out.println(c); //  这一句不会被执行
}

}


异常处理的第二种方式: throw 和 throws

throw 和 throws:抛出异常 throw 写在方法内部,throws 写在方法声明上,当方法里的异常向外抛的时候,它会抛向调用它的函数里,如何调用的函数没有进行处理,则继续向上抛,一直到达main方法,如果main方法也没有处理,则交由JVM处理

public static void method() throws Exception {
// TODO Auto-generated method stub
System.out.println("抛出异常之前");
if (true){
throw new Exception();   // 程序抛出了异常之后,后面的代码也就不执行了
//  而且编译器也不允许你在后面再添加语句了,后面这一句输出添加到代码上会报错
// System.out.println("抛出异常之后");
}
System.out.println("抛出异常之后"); // 不会被执行
}


对于非运行时异常(checked exception) ,必须要对其进行处理,处理方式有两种:

第一种是使用 try.. catch…finally 进行捕获;

第二种是在调用该会产生异常的方法所在的方法声明 throws Exception

对于运行时异常(runtime exception) ,我们可以不对其进行处理,也可以对其进行处理。 推荐不对其进行处理。

需要注意的是: 不管是运行时的异常,还是非运行时的异常,如果一直往外抛异常,到了main函数里面还没有被处理,则程序会终止,下面的语句不会被执行。

NullPointerException 是空指针异常,该异常在编程的过程中会经常出现, 出现该异常的原因在于某个引用为 null,但你却调用了它的某个方法。这时就会出现该异常。

自定义的异常:实现比较简单,只要实现两个构造方法就可以,里面写一句 super()

// 自定义一个异常,定义构造方法就行,它会一层一层向上传
public class MyException extends  RuntimeException{
public MyException () {
// TODO Auto-generated constructor stub
super();
}
public MyException (String message) {
// TODO Auto-generated constructor stub
super(message);
}
}

// 自定义一个异常,定义构造方法就行,它会一层一层向上传
public class MyException2 extends  RuntimeException{
public MyException2 () {
// TODO Auto-generated constructor stub
super();
}
public MyException2 (String message) {
// TODO Auto-generated constructor stub
super(message);
}
}


主要注意的一点:

我们可以使用多个 catch块来捕获异常,这时需要将父类型的 catch块放到子类型的catch 块之后,这样才能保证后续的 catch 可能被执行,否则子类型的 catch 将永远无法到达,Java 编译器会报编译错误;如果多个 catch 块的异常类型是独立的 (MyException, MyException2 ), 那么谁前谁后都是可以的。 因为异常的匹配是从前往后匹配的,当父类的catch放前面的时候,一个子类的异常也可以被父类捕获到,后面的就不会再被执行了。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: