Throwable
,名为Exception
,它有很多子类,分别描述了系统中很多常见的异常情况,这些异常机制的出现使得编写程序时对一些问题的处理变得尤为方便,下面是一些简单的使用情况。/**
* javac ExceptionDemo.javac
* java ExceptionDemo
* 输出:String index out of range: 3
*/
class ExceptionDemo {
public static void main(String[] args) {
try {
// 可能产生异常的代码放到try内
System.out.println("Hi".charAt(3));
} catch(Exception e) {
// 对异常的处理
System.out.println(e.getMessage());
}
}
}
catch
中的Exception
换成StringIndexOutOfBoundsException
时,输出结果同样为String index out of range: 3
,如下:这里Exception
是StringIndexOutOfBoundsException
的父类,子类的对象赋值给父类的类型,这在Java中称作多态。/**
* 输出:String index out of range: 3
*/
class ExceptionDemo {
public static void main(String[] args) {
try {
// 可能产生异常的代码放到try内
System.out.println("Hi".charAt(3));
} catch(StringIndexOutOfBoundsException e) {
// 对异常的处理
System.out.println(e.getMessage());
}
}
}
Exception
的继承关系图可以清楚的知道Exception
的父类及其子类的关系,超类是Throwable
(Error
和Exception
的共同超类),Throwable
的超类便是Object
(除本身外Java中所有类的直接或者间接超类)。以Exception
结尾的类都是继承自Exception
。try
内有多条语句时,可能会产生多种异常,下列代码虽然加上了异常捕获操作但是没有还是产生了异常,程序崩溃。/**
* 输出:H
* Exception in thread "main" java.lang.ArithmeticException: / by zero
* at ExceptionDemo3.main(ExceptionDemo3.java:10)
*/
class ExceptionDemo3 {
public static void main(String[] args) {
try {
// 可能产生异常的代码放到try内
System.out.println("Hi".charAt(0));
System.out.println(123 / 0);
} catch(StringIndexOutOfBoundsException e) {
// 对异常的处理
System.out.println(e.getMessage());
}
}
}
StringIndexOutOfBoundsException
异常,这条异常只有System.out.println("Hi".charAt(0));
才会产生。而System.out.println(123 / 0);
这条语句会产生另一种异常,叫做ArithmeticException
,即运算异常。而这条异常没有相应的捕获语句,所以虚拟机采用默认处理方式,即让程序崩溃。ArithmeticException
异常捕获后便可以正常处理异常,如下:/**
* 输出:H
* 异常:/ by zero
*/
class ExceptionDemo3 {
public static void main(String[] args) {
try {
// 可能产生异常的代码放到try内
System.out.println("Hi".charAt(0));
System.out.println(123 / 0);
} catch(StringIndexOutOfBoundsException e) {
// 对异常的处理
System.out.println(e.getMessage());
} catch(ArithmeticException e) {
System.out.println("异常:" + e.getMessage());
}
}
}
catch
?当然你可以像第一个示例那样使用Exception
来接收所有异常,但是这样又会有问题,那就是所有异常都会统一处理,那么就使用Exception
和其他异常混合使用的情况,这种情况的时候要注意一点,Exception
一定要放在最后面一条catch
中,否则编译会报错。正确写法如下:
/**
* 输出:H
* 异常:/ by zero
*/
class ExceptionDemo3 {
public static void main(String[] args) {
try {
// 可能产生异常的代码放到try内
System.out.println("Hi".charAt(0));
System.out.println(123 / 0);
} catch(StringIndexOutOfBoundsException e) {
// 对异常的处理
System.out.println(e.getMessage());
} catch(ArithmeticException e) {
System.out.println("异常:" + e.getMessage());
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
}
finally
关键字finally
,同catch
的用法类似,不过finally
后没有类型,finally
的功能是作为try...catch...finally
中必然执行的一段。也就是说try
内的代码产生或者没有产生异常,最终都会执行finally
内的代码。这可以应用到一些网络操作中,如访问数据库时有打开数据库,当操作数据库时出现了错误,那么在finally
中写上关闭数据库的操作便起到了很好的作用。避免系统打开很多数据库连接而无法关闭且又无法操作,这样会非常消耗系统资源。访问网络时也是同样的道理。一些finally
的演示如下:/**
* 输出:
* B
* C
*/
class ExceptionDemo4 {
public static void main(String[] args) {
try {
int num = 4 / 0; // 制作异常
System.out.println("A");
} catch (Exception e) {
System.out.println("B");
} finally {
System.out.println("C");
}
}
}
/**
* 输出:
* A
* B
* C
*/
class ExceptionDemo4 {
public static void main(String[] args) {
try {
System.out.println("A");
int num = 4 / 0; // 制作异常
} catch (Exception e) {
System.out.println("B");
} finally {
System.out.println("C");
}
}
}
/**
* 输出:
* 4
* 4
* 0
*/
class ExceptionDemo4 {
public static void main(String[] args) {
int num = 4;
try {
System.out.println(num);
int n = 10 / 0; // 制造异常
num += 2; // 异常发生后会立即进入异常处理部分
} catch (Exception e) {
System.out.println(num);
num = 0;
} finally {
System.out.println(num);
}
}
}
try
内的代码在执行时碰到了异常后便不再继续执行,而是跳到对应的异常处理代码段执行,然后再执行finally
段的代码。finally
的执行如下:/**
* 输出:
* try:4
* catch:4
* finally:5
* main:4
*/
class ExceptionDemo5 {
public static void main(String[] args) {
System.out.println("main:" + method());
}
public static int method() {
int num = 4;
try {
System.out.println("try:" + num);
int n = 10 / 0; // 制造异常
} catch (Exception e) {
System.out.println("catch:" + num);
return num;
} finally {
num ++;
System.out.println("finally:" + num);
}
return 0;
}
}
finally
之前出现了return
语句时,返回值的内容会被压栈,所以在finally
中修改num
的值是不会影响最终在main
函数中接收到的返回值的内容的,这也体现了finally
一定会执行的一点。import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 文件内容为:Hello
* 若将System.exit(0);注释掉,文件内容为Hi
*/
class ExceptionDemo5 {
public static void main(String[] args) {
try {
FileOutputStream fout = new FileOutputStream(new File("E:\\ex.txt"));
fout.write("Hello".getBytes());
fout.close();
System.exit(0); // 直接退出系统
} catch (IOException e) {
} finally {
try {
FileOutputStream fout = new FileOutputStream(new File("E:\\ex.txt"));
fout.write("Hi".getBytes());
fout.close();
} catch (IOException e) {
}
}
}
}
finally
的内容必然执行也是要建立再程序还处于正在运行的状态,程序已退出虚拟机当然无法再执行finally
的内容了。try...finally
组合除了try...catch...finally
还有一种try...finally
组合方式,即去掉catch段。若代码段抛出的是RuntimeException
便将异常抛给上一层,若是非RuntimeException
或其子类便会编译错误。(ArithmeticException
属于RuntimeException
)
/**
* 输出:
* method:finally
* main:/ by zero
*/
class ExceptionDemo6 {
public static void main(String[] args) {
try {
method();
} catch(Exception e) {
System.out.println("main:" + e.getMessage());
}
}
public static void method() {
try {
int num = 6 / 0;
} finally {
System.out.println("method:finally");
}
}
}
throws
try...catch
,可以使用try...catch...finally
,也可以使用try..finally
,当然还有其他方式,你可以使用throws
把异常抛给上一层,这里的上一层指的是如main
函数调用method
方法,对于method
方法来说main
函数就是上一层。/**
* 输出:
* main:Hello
*/
class ExceptionDemo7 {
public static void main(String[] args) {
try {
method();
} catch(ClassNotFoundException e) {
System.out.println("main:" + e.getMessage());
}
}
public static void method() throws ClassNotFoundException {
Class<?> c = Class.forName("Hello");
}
}
throws
后面使用,
隔开,而抛出一条异常是使用throw
来实现的,如下:/**
* 输出:
* main:-Message-
*/
class ExceptionDemo7 {
public static void main(String[] args) {
try {
method();
} catch(ClassNotFoundException e) {
System.out.println("main:" + e.getMessage());
} catch(Exception e) {
System.out.println("main:" + e.getMessage());
}
}
public static void method() throws ClassNotFoundException, IllegalAccessException {
// Class<?> c = Class.forName("Hello");
throw(new IllegalAccessException("-Message-"));
}
}
Exception
即可,或者继承Exception
的子类,如下:/**
* 输出:
* main:My Exception
*/
class MyException extends Exception {
public MyException(String msg) {
super(msg);
}
}
class ExceptionDemo7 {
public static void main(String[] args) {
try {
method();
} catch(MyException e) {
System.out.println("main:" + e.getMessage());
}
}
public static void method() throws MyException {
throw(new MyException("My Exception"));
}
}
RuntimeException
简介RuntimeException
或者RuntimeException
的子类时无需使用throws
在方法名后面标出,这一类异常可能无法通过捕获处理很好地处理,如除零错误发生时即使捕获到了异常,但是后面的运算结果是会受到影响的,一定会出现一个不正确的运算结果。如上面出现过的除零异常,无需在方法名后加异常类型说明:/**
* 输出:
* method:finally
* main:/ by zero
*/
class ExceptionDemo6 {
public static void main(String[] args) {
try {
method();
} catch(Exception e) {
System.out.println("main:" + e.getMessage());
}
}
public static void method() /*这里不需要加 ArithmeticException*/{
try {
int num = 6 / 0;
} finally {
System.out.println("method:finally");
}
}
}
原文地址:http://blog.csdn.net/decting/article/details/43955609