Java 异常
1、异常简介
Java 异常是程序中的某些错误,是Java 提供的一种面对程序运行错误时 提供的 应对机制。
在程序运行时抛出异常可以使程序不中断的运行下去,开发或维护人员能够了解异常的起因、异常的发生处以及抛出了什么异常。
异常结构:

error :出现error 基本上是硬件出错,说明程序崩了
exception:出现异常基本上是 编码、环境、用户操作或者输入问题
runtimeException 运行时异常:Java虚拟机会自动抛出,绝大部分都说明了代码本身有问题
checkException 检查异常:需要手动添加捕获及处理语句
-----
运行时异常和检查异常的区别:
运行时异常又叫非检查异常,一般情况下不需要程序员主动的捕获,但是一旦抛出了异常,就会一层层往上抛,如果最上层也没有相应的处理代码,此时程序就会中断。也因此,若想进程一直持续运行,那么对于所有可能会抛出异常的代码块,都要给他加上try catch 捕获并作出相应的异常处理机制。
检查异常是Java编译器强制要求必须要显示捕获的异常。
2、try catch finally 语句块
try:可能抛出异常的语句
catch: 异常处理的信息,可以打印异常日志、输出系统提示啥的;有可能一段代码会抛出多个异常,这时可以用多个catch块来捕获异常,catch块要遵循先子类后父类异常的原则
finally: 最终执行的,可用来关闭资源等
3、关于在finally前return
finally 是在try catch 语句块中的return “执行完之后,返回调用前” 执行的;
如果try catch finally 中都没有return ,那会调用在最后面的return
public static void main(String[] args){
//finally在前面的return “执行完之后,返回调用前执行”, 一定会执行!
int test1 = testTryCatch();
System.out.println(test1);
/**
* 不捕获异常:
* 我是finally语句块,最终执行的是我
1
* 捕获异常:
* java.lang.ArrayIndexOutOfBoundsException: 2
at test.TestException.testTryCatch(TestException.java:65)
at test.TestException.main(TestException.java:8)
我是catch块,我捕获异常了
我是finally语句块,最终执行的是我
0
*/
}
public static int testTryCatch(){
int[] nums = new int[2];
nums[0] = 1;
try{
//System.out.println(nums[2]);
return nums[0];
}catch(Exception e){
e.printStackTrace();
System.out.println("我是catch块,我捕获异常了");
//在catch块中return,后面还有finally的情况下,先把return的值执行了或者说先行保留,
//等finally执行完在返回给这个方法的调用
return nums[0] = 0;
}finally {
System.out.println("我是finally语句块,最终执行的是我");
}
}
4、异常抛出
throws:声明将要抛出何种类型的异常,在类或方法中声明,返回给上层调用者处理异常;throws exception1,exception2
throw:将产生异常的动作抛出,表示这个动作,相当于try catch; throw new exception("产生异常了");
public static void main(String[] args){
//这里属于起始调用者,就直接自己处理异常即可,
//如果不是起始调用者或者处理不了异常代码,就继续throw异常,并在方法名上声明要抛出
try {
testThrowException();
} catch (Exception e) {
e.printStackTrace();
}
/**
* java.lang.Exception
at test.TestException.testThrowException(TestException.java:78)
at test.TestException.main(TestException.java:12)
*/
}
//在方法内部会抛出异常的时候,在方法头要声明这个方法会抛出异常,有多个异常的话就用逗号隔开
//在调用这个方法的时候,要么自己try catch处理这个异常,要么在调用这个方法的方法声明处声明会抛出异常,丢给起始调用者处理异常
public static void testThrowException() throws Exception{
if(true){
throw new Exception();
}
}
注意抛出和捕获的区别:
抛出就是我发现这个异常,谁调用我,就把这个异常丢给谁来处理
捕获就是,我发现这个异常,我自己来处理
通常情况下,如果要调用可能会抛出异常的方法或代码块,就用try catch来被捕获处理这段调用代码,此时,一旦调用方法抛出异常,就会被trycatch捕获并且处理,这样主程序就不会中断了。
5、自定义异常
一般情况下,直接继承Exception的会是检查性异常
直接继承RuntimeException 的当然是运行时异常
如果只是在已有异常的基础上修改某些逻辑,则可以直接继承该异常

6、异常链
把捕获的异常包装成新的异常,在新的异常里面添加对原始异常的引用,在把新异常抛出,类似链式反应,一个导致另外一个,这种就叫异常链。
(所以一般在程序抛出异常时,最下面的那个cause by 往往是直接原因)
public static void main(String[] args){
//因为把自定义异常包装成了RuntimeException,所以这里就不需要自己显示捕获异常了
testChainException();
/**
* 可见这里执行之后先抛出运行时异常,下面的Caused by 才是原本自定义的异常
* 也因为这个原因,在Java代码编写中,一般抛出异常,最下面的才是最主要的原因
*
* Exception in thread "main" java.lang.RuntimeException: 把自定义异常包装成运行时异常!
at test.TestException.testChainException(TestException.java:88)
at test.TestException.main(TestException.java:33)
Caused by: test.TestSelfException: 自定义异常:就是异常了!
at test.TestException.testSelfException(TestException.java:77)
at test.TestException.testChainException(TestException.java:86)
... 1 more
*/
}
/**
* 自定义异常
* @throws TestSelfException
*/
public static void testSelfException() throws TestSelfException{
if(true){
throw new TestSelfException("自定义异常:就是异常了!");
}
}
/**
* 异常链
*/
public static void testChainException(){
try {
testSelfException();
} catch (TestSelfException e) {
RuntimeException rte = new RuntimeException("把自定义异常包装成运行时异常!");
rte.initCause(e);
throw rte;
}
}
7、应用总结

最好是在打印异常的同时加上业务回滚之类的,具体的看具体业务

浙公网安备 33010602011771号