学习了解
- 异常处理的作用
- Java异常体系结构简介
学习了解
- try-catch以及try-catch-finally
- 抛出异常
- 自定义异常
- 异常链
在Java中,阻止当前方法和作用域继续执行的称为异常。

在Java异常体系中,Throwable类是所有异常的父类,主要有两个子类,一个是Error类,一个是Exception类。Error类一般不常见,比如虚拟机错误(VirtualMachineRrror)线程死锁(ThreadDeath),最好不要期待它的出现,一般没有办法处理。
Exception异常出现的原因一般是编码、环境、用户操作输入出现问题等等,它有很多子类,比如非检查异常(RuntimeException)和检查异常。
非检查异常(RuntimeException)的异常类型有很多,比如引用了空对象的属性或方法(NullPointerException),数组越界(ArrayIndexOutOfBoundsException),类型转换出错(ClassCastException),还有可能是算数异常(ArithmeticException)等等。RuntimeException会由Java虚拟机自动抛出并自动捕获,它的出现一般说明你的代码逻辑有问题,你应该去改进代码。
检查异常的出现也多种多样,比如文件异常(IOException),SQL异常(SQLException),各种奇葩。一般需要手动的添加捕获处理语句。
在Java中使用try-catch以及try-catch-finally语句块来捕获或处理异常。
try{
//一些会抛出异常的方法
} catch (Exception e) { //catch中来捕获会出现异常的类型
//处理该异常的代码块
}
如果try抛出异常首先抛出异常的代码块会终止执行,接着程序的控制权将被交给catch块中的异常处理程序 。值得注意的是在try-catch语句块中的代码执行完毕之后在catch块外的程序语句会正常执行。
如果try语句块会抛出多种异常,就使用多重catch来捕获。在使用多重catch的时候值得注意的是顺序问题,一定要先小后大,先子类后父类来编写多重catch语句块,因为当出现异常的时候异常处理系统会就近寻找匹配的异常处理程序。
有时候在try-catch语句块中代码执行完毕后要进行一些善后工作,比如关闭数据库的连接,释放文件资源等等,这时候就要使用到finally语句块
try{
//一些会抛出异常的方法
} catch (Exception e) { //catch中来捕获会出现异常的类型
//处理该异常的代码块
}finally {
//最终将要执行的代码
}
范例:try-catch语句使用
/**
* Created by 99479 on 2017/6/30.
*/
public class TryCatchTest {
public static void main(String[] args) {
TryCatchTest tryCatchTest = new TryCatchTest();
int result = tryCatchTest.test();
System.out.println("text方法执行完毕,返回值为:"+result);
}
/**
*
* divider 除数
* @return result 结果
* 每次循环,dicider减一,result = result+100/divider
* 如果:捕获异常,打印输出“抛出异常了!!!”。返回-1
* 否则返回result
*/
public int test(){
int divider = 10;
int result = 100;
try{
while (divider > -1){
divider --;
result = result + 100 /divider;
}
}catch (Exception e){
e.printStackTrace();//打印异常信息
System.out.println("循环抛出异常了!!!");
}
return -1;
}
}
** 输出结果**
java.lang.ArithmeticException: / by zero
at TryCatchTest.test(TryCatchTest.java:25)
at TryCatchTest.main(TryCatchTest.java:7)
循环抛出异常了!!!
text方法执行完毕,返回值为:-1
Process finished with exit code 0
** 范例:try-catch-finally的使用**
/**
* Created by 99479 on 2017/6/30.
*/
public class TryCatchFinallyTest {
public static void main(String[] args) {
TryCatchFinallyTest tryCatchFinallyTest = new TryCatchFinallyTest();
int result = tryCatchFinallyTest.test();
System.out.println("我想大声告诉你!text()执行完毕!!!");
System.out.println("我的值为:"+result);
}
/**
*
* divider 除数
* @return result 结果
* 每次循环,dicider减一,result = result+100/divider
* 如果:捕获异常,打印输出“抛出异常了!!!”。返回999
* 否则返回result
* finally: 打印输出“这是finally !!!哈哈”,同时打印输出result的值
*/
private int test(){
int divider = 10;
int result = 100;
try{
while (divider > -1){
divider --;
result = result + 100 /divider;
}
}catch (Exception e){
e.printStackTrace();//打印异常信息
System.out.println("循环抛出异常了!!!");
}
finally {
System.out.println("这是finally !!!哈哈");
System.out.println("我是result,我的值是:"+result);
}
return result = 999;
}
}
** 输出 **
java.lang.ArithmeticException: / by zero
循环抛出异常了!!!
这是finally !!!哈哈
at TryCatchFinallyTest.test(TryCatchFinallyTest.java:28)
我是result,我的值是:381
我想大声告诉你!text()执行完毕!!!
at TryCatchFinallyTest.main(TryCatchFinallyTest.java:7)
我的值为:999
Process finished with exit code 0
Java中的异常抛出##
在Java异常体系中,使用throw和throws关键字进行异常的抛出。
throws —— 声明将要抛出何种类型的异常(声明)
public void 方法名(参数列表)throws异常列表{//调用者会抛出异常的方法或者:throw new Exception();}
** 示例 **
public void divide(int one,int two)throws Exception{
if (two == 0){
throw new Exception("两数相除,除数2不能为0");
}else {
System.out.println("两数相除,结果为:"+one/two);
}
}
** 解决方法 **
- 在调用处是用try-catch捕获异常
public void compute(){
/*
*此处省略代码
*/
try{
divide(5,0);
}catch (Exception e){
System.out.println(e.getMessage());
}
}
- 调用方法使用throws继续抛出
public void compute() throws Exception{
/**
* 此处省略代码
*/
divide(5,0);
}
自定义异常##
有时候由于我们的业务或者实际应用场景中没有Java类库所定义的异常,比如我想要一个喝大了的异常,这时候就需要我们自定义异常。
定义方法:class 自定义异常类 extends 异常类型{}
** 示例 **
public class DrunkException extends Exception {
public DrunkException(){
}
public DrunkException (String mesage){
super(mesage);
}
}
异常链
有时候可以把捕获的异常包装成新的异常,然后在新的异常添加对原始异常的引用,然后再把新的异常抛出,他们就象是链式反应一样,一个导致另一个,在Java中这种情况就叫做异常链。
** 示例 **
/**
* Created by 99479 on 2017/7/1.
*/
public class ChainTest {
/**
* test1(): 抛出“喝大了”异常
* text2(): 调用test1(),捕获“喝大了”异常,并包装成运行时异常,继续抛出
* main方法中,调用test2(),尝试捕获test2()方法抛出的异常
*/
public static void main(String[] args) {
ChainTest chainTest = new ChainTest();
try {
chainTest.test2();
} catch(Exception e){
e.printStackTrace();
}
}
public void test1() throws DrunkException{
throw new DrunkException("喝车别开酒!");
}
public void test2(){
try {
test1();
} catch (DrunkException e) {
RuntimeException neweExc = new RuntimeException("司机一滴酒,亲人两行泪~~~");
//调用此方法去引用原始异常
neweExc.initCause(e);
throw neweExc;
}
}
}
** 输出 **
java.lang.RuntimeException: 司机一滴酒,亲人两行泪~~~
at ChainTest.test2(ChainTest.java:29)
at ChainTest.main(ChainTest.java:14)
Caused by: DrunkException: 喝车别开酒!
at ChainTest.test1(ChainTest.java:21)
at ChainTest.test2(ChainTest.java:26)
... 1 more
** 简便方法示例 **
/**
* Created by 99479 on 2017/7/1.
*/
public class ChainTest {
/**
* test1(): 抛出“喝大了”异常
* text2(): 调用test1(),捕获“喝大了”异常,并包装成运行时异常,继续抛出
* main方法中,调用test2(),尝试捕获test2()方法抛出的异常
*/
public static void main(String[] args) {
ChainTest chainTest = new ChainTest();
try {
chainTest.test2();
} catch(Exception e){
e.printStackTrace();
}
}
public void test1() throws DrunkException{
throw new DrunkException("喝车别开酒!");
}
public void test2(){
try {
test1();
} catch (DrunkException e) {
RuntimeException neweExc = new RuntimeException(e);
throw neweExc;
}
}
}
** 输出 **
java.lang.RuntimeException: DrunkException: 喝车别开酒!
at ChainTest.test2(ChainTest.java:28)
at ChainTest.main(ChainTest.java:14)
Caused by: DrunkException: 喝车别开酒!
at ChainTest.test1(ChainTest.java:21)
at ChainTest.test2(ChainTest.java:26)
... 1 more
** 经验总结 **
- 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理。
- 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常。
- 对于不太确定是否可能抛出异常的代码,也可以加上try-catch,处理潜在的异常。
- 尽量去处理异常,切记只是简单的调用printStackTrace()去打印输出。
- 具体如何处理异常,要根据不同的业务需求和异常类型去决定。
- 尽量添加finally语句块去释放占用的资源。
网友评论