异常
异常,即不正常的事或物。
而在程序范畴中,异常是指使程序无法正常运行的错误或外部问题。
Throwable 类
在Java中,当程序无法正常运行时,通常是出现了错误或者异常。
这时JVM会开始判断,如果是异常,则会创建相应的异常实例,然后抛出给调用者。如果是错误,则进行报错。
这里提到了错误和异常,Java语言将他们定义为Error和Exception类,他们都继承自Throwable类
,继承关系如下:
这里列举一些常见的Error和Exception子类:
父类 | 类名 | 相关信息 |
---|---|---|
Error | OutOfMemoryError | 内存耗尽 |
Error | NoClassDefFoundError | 无法加载某个Class |
Error | StackOverflowError | 栈溢出 |
RuntimeException(illegalargumentexception) | NumberFormatException | 数值类型的格式错误 |
RuntimeException | NullPointerException | 对某个null的对象调用方法或字段 |
RuntimeException | IndexOutOfBoundsException | 数组索引越界 |
IOException | FileNotFoundException | 未找到文件 |
IOException | SocketException | 读取网络失败 |
异常处理
Java中,异常的出包含两种,一种是捕获,另一种是抛出。
捕获异常
语法:try...catch...finally
try{
}catch (Exception e){
e.printStackTrace();
}finally {
}
总结:
- try块内某行代码出现异常时,该行代码后的代码将不再被执行,直接进入catch块或者finally块。
try{quan
// do sth --√
// do sth --√
// sth wrong --Oops!
// break out --×
// not to do this --×
}catch (Exception e){
e.printStackTrace(); // --√
}finally {
// --√
}
-
通常不用分步捕获,而用Exception类统一捕获,然后用printStackTrace打印堆栈追踪。
-
finally块的代码将作为函数复制于在try和catch的最后,并在return或throw之前。
-
通常情况下,finally中不使用return/break/continue/throw/goto跳转语句,因为这会导致try或catch中的异常不被捕获以及return失效。
-
finally块内代码在某些情况下不会执行,如:块内异常;线程死亡;进程结束;硬件问题。
注意:
- 请重视
空指针
异常,切记先判断是否非空,在进行调用。 - finally的经典应用为文件读写操作时的
关闭流
。 - finally还有一个细节需要重视!细节就是finally里对基本数据类型参数的操作采用的是
值传递
,对引用类型参数的操作为引用传递。
抛出异常
异常传播
当某个方法抛出了异常时,如果当前方法没有捕获异常,异常就会被抛到上层调用方法,直到遇到某个try ... catch ...
将其捕获为止。
抛出处理
抛出异常有两种定义方法,它们分别是throw和throws。
/**
* Example for throw & throws
* @throws Exception
*/
public static void doSthDangerous() throws Exception{
throw new Exception();
}
面试题
- 主函数catch块中抓到的是哪个异常?
package cn.charliejohn.handlexexception;
public class Helloxexceptionx1 {
public static void main(String[] args) {
try{
System.out.println("The answer is " + sthDangerous()+".");
}catch(Exception e){
// 答:
// 1. 主函数中没能捕获到异常,因为finally在抛异常前return true。
System.out.println("Exception from main.");
e.printStackTrace();
}
}
public static boolean sthDangerous(){
try {
throw new Exception("Try in sthStrange.");
} finally {
return true;
}
}
}
/**
* The answer is true.
* **/
- How much the answer is?
package cn.charliejohn.handlexexception;
public class Helloxexceptionx2 {
public static void main(String[] args) {
try{
// 答:
// 2. The answer is 0. Because the i in finally is another i.
System.out.println("The answer is " + sthStrange()+".");
}catch(Exception e){
e.printStackTrace();
}
}
public static int sthStrange(){
int i = 0;
try {
i = i/0;
} catch (Exception e) {
e.printStackTrace();
return i;
} finally {
++i;
}
return 100;
}
}
/**
* java.lang.ArithmeticException: / by zero
* at cn.charliejohn.handlexexception.Helloxexceptionx2.sthStrange(Helloxexceptionx2.java:18)
* at cn.charliejohn.handlexexception.Helloxexceptionx2.main(Helloxexceptionx2.java:9)
* The answer is 0.
* **/
- 综合案例
package cn.charliejohn.handlexexception;
import java.io.*;
/**
* 1. 主函数catch块中抓到的是哪个异常?
* 2. sthStrange的结果是多少?
* 3. sthDangerous会抛出"Not important."异常吗?
* **/
public class Hixexception
{
// The exception throws in main is because
// there is throws in finally.
public static void main(String[] args) throws Exception {
try{
// The answer is 1, because the i in finally is another i;
System.out.println("The answer is " + sthStrange());
}catch(Exception e){
// The exception handle by sthStrange itself,
// so there is not exception from main.
System.out.println("Exception from main");
e.printStackTrace();
}finally {
// Call sthDangerous to prove that
// return in finally will blocks exception in try.
System.out.println(sthDangerous());
System.out.println("Finally from main");
}
}
/**
* Sth strange happen when transmit i.
* @return
*/
public static int sthStrange(){
int i = 0;
OutputStream out = null;
try {
int j = 0;
out = new FileOutputStream("D://nothing.md");
// Exception occurs.
j = j / 0;
System.out.println("Try in sthStrange.");
} catch (Exception e) {
e.printStackTrace();
System.out.println("Catch in sthStrange.");
return i;
} finally {
try {
if (out != null) {
System.out.println("Finally try in sthStrange.");
out.close();
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Finally in sthStrange.");
++i;
}
return 100;
}
/**
* Sth dangerous happen when finally return.
* @return
*/
public static boolean sthDangerous() throws Exception{
try {
// This exception will no be taken into account.
// Because it will be blocked by finally return.
throw new Exception("Not important.");
} finally {
System.out.println("Finally in sthDangerous.");
return false;
}
}
}
/**
* java.lang.ArithmeticException: / by zero
* at cn.charliejohn.handlexexception.Hixexception.sthStrange(Hixexception.java:40)
* at cn.charliejohn.handlexexception.Hixexception.main(Hixexception.java:17)
* Catch in sthStrange.
* Finally try in sthStrange.
* Finally in sthStrange.
* The answer is 0
* Finally in sthDangerous.
* false
* Finally from main
*
* Process finished with exit code 0
* **/
文件输出: