Java异常类¶
约 1142 个字 233 行代码 1 张图片 预计阅读时间 7 分钟
Java中的异常体系¶
在Java中,异常类的父类为Throwable
类,在Throwable
下,存在两个子类:
Error
类:错误类,一般错误类中的错误都是致命错误,例如栈溢出错误StackOverflowError
Exception
类:异常类,一般是小型错误,例如数组越界ArrayIndexOutofBoundException
一般情况下Exception
类是编译时异常,但是其中有一个特殊的异常RuntimeException
,该异常为运行时异常,例如数组越界异常就属于RuntimeException
上面的体系可以参考下图:
区分一个异常类属于编译时异常还是运行时异常可以看该异常类是否直接继承Exception
类,如果是则是编译时异常,否则继承自RuntimeException
代表运行时异常
抛出异常¶
在Java中,使用throw
关键字抛出异常对象,基本格式如下:
Java | |
---|---|
1 |
|
例如下面的代码:
Java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Note
需要注意的是,如果抛出的异常属于编译时异常,那么必须在方法形参后使用throws
关键字抛出,否则编译不通过
处理异常¶
处理异常的两种方式¶
在Java中一共有两种处理异常的方式:
-
使用
throws
关键字抛出当前方法中的异常,如果一个方法有多个异常抛出,可以使用,
分隔不同的异常类,使用格式如下:Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14
方法(形参列表) throws 异常类名1, 异常类2... { // 方法体 throw new 异常对象名(); } // 例如 public static void method(String s) throws FileNotFoundException { if(!s.endsWith(".txt")) { throw new FileNotFoundException("文件不存在"); } else { System.out.println("文件存在"); } }
-
使用
try...catch
捕获异常,使用try
包裹可能出现异常的语句,catch
捕获异常对象,catch
语句可以不止一个,基本格式如下:Java 1 2 3 4 5 6 7 8
try{ // 可能出现异常的语句 } catch(异常类 异常对象名) { // 处理语句 } // 可以有多个catch语句
例如下面的代码:
Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
public class Test { public static void main(String[] args) { String s = "test.txt1"; try { method(s); } catch (FileNotFoundException e) { System.out.println(e); // 也可以使用下面的方式打印完整信息 // e.printStackTrace(); } } public static void method(String s) throws FileNotFoundException { if (!s.endsWith(".txt")) { throw new FileNotFoundException("文件不存在"); } else { System.out.println("文件存在"); } } }
或者使用一个
catch
,在catch
中捕获多个异常类,使用|
分隔,但是不推荐,例如:Java 1 2 3 4 5 6 7
try{ // 可能出现异常的语句 } catch(异常类1 | 异常类2 | ... 异常类n 异常对象名) { // 处理语句 }
在处理异常时,如果抛出的异常类是另一个异常类的子类,那么可以使用throws
向上抛出对应父类异常类,例如上面的FileNotFoundException
属于父类IOException
,所以可以抛出IOException
或者Exception
同样,对于try...catch
语句也是如此
Java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
如果可能出现的异常语句在try
中确实出现了异常,则当前try
中出现异常的语句之后的语句不会再执行,否则正常执行,例如下面的代码:
Java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
try...catch
和throws
的区别¶
使用throws
处理异常时,第一个出现异常的位置开始抛出异常,此时该方法不再执行剩余的代码,将异常向方法调用处抛,如果方法调用处依旧没有处理异常,则继续向上抛出,以此类推,如果最后一个调用处依旧没有处理,则此时JVM就会报错,打印对应的异常信息
使用try...catch
处理异常时,如果catch
可以捕获到try
中的异常,则代表异常被正常处理,此时其他的catch
将不会被执行(即从上而下依次匹配直到遇到合适的),但是不可以将父类异常放在子类异常前,否则编译报错,当正常处理完异常后,try...catch
后面的语句将正常执行
finally
关键字¶
finally
关键字用于一定要执行的代码,放在最后一个catch
之后,有了finally
后,不论是否出现了异常,都会走finally
中的语句,除非在可以捕获到对应异常的catch
语句中使用了System.exit(0)
(结束JVM虚拟机运行),例如下面的代码:
Java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
一般使用finally
在关闭资源时,因为部分情况下GC(垃圾回收器)无法回收堆内存中的文件,从而无法释放内存,此时需要在finally
中手动关闭资源
抛出异常注意事项¶
- 如果父类方法已经抛出了异常,子类重写父类对应的方法就可以不再抛出异常
- 如果父类方法没有抛出异常,子类重写父类对应的方法就不要抛出异常
例如下面的代码:
Java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
自定义异常类¶
如果想要自定义一个异常类,则自定义的类就必须继承自Exception
,否则编译器不会将其当作异常类,格式如下:
Java | |
---|---|
1 2 3 |
|
例如下面的代码:
Java | |
---|---|
1 2 3 |
|
Java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
如果想添加自定义异常信息,需要提供一个有参构造函数,该构造函数使用一个String
类型的message
构造对象,此时会调用父类的构造函数,因为Exception
类中存在对应的构造函数
Java | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
Java | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|