Java 基础>14 - 异常、finally块

学习总结:
链接:【Java基础、springboot、springcloud、docker 等,学习目录】

异常:

Java 程序中不正常的情况统称为异常。异常体系包含在java·lang 包中。

java异常体系
|——Throwable  (所有异常或错误类的超类)
     |——Error (错误)一般由jvm或硬件引发的问题,一般不通过代码去处理,运行时期才具有。
	 |——Exceprion (异常)需要通过修改代码去处理
		  |——RuntimeException (运行时异常)
		  |——非运行时异常  编译期间

异常的处理:

1、由jvm处理:jvm有默认的异常处理机制。
jvm检测到异常,将异常抛给方法调用者,最终由main方法接收到异常也不处理,将异常抛给main的调用者jvm。
jvm接收到异常的处理:
a、将异常信息输出到控制台。
b、终止程序、结束(一旦异常被抛出了,后面的所有程序不在执行)。

2、自己处理:捕获处理、抛出处理。

一、捕获处理:

 try{
     /**
      * jvm 在执行这段代码的时候发现不正常的情况,就会创建一个对应的 **异常对象** 
      */
    // 可能出现异常的代码...
     
 } catch (捕获的异常类型 变量名){  // 例:Exception  e --> e 指向了try 中的异常对象
     // 处理异常的代码...
     
 } finally {
     // 必须要执行的代码...
 }

细节:
1、若果try块中出现了异常,继而执行catch块中的代码,那么try - catch 块之外的代码可以正常执行了。
2、try块中出现了异常的代码,那么try块中异常代码之后的代码不会执行了。
3、一个try 块后面可以跟随很多catch 块,即:一个 try 块可以捕获多种异常。
4、一个try 块可以捕获多种类型的异常,但是捕获的类型必须从小到大进行,否则编译报错(从大到小,后面的代码块永远不会执行)。平级异常:没有顺序。

二、抛出异常:throw、throws
throw用于方法内部抛出异常对象,一次只能抛一个对象、throws用于方法声明上抛出异常类型,可同时抛多个类。

细节:
1、如果一个方法的内部抛出了一个编译时异常对象,那么必须要在方法声明上抛出。
2、若果调用了一个已经声明抛出编译时异常的方法,那么调用者必须处理异常(两种处理方式)。
3、方法内部throw 后面的代码都不会在执行了。

自定义异常类:

sun 公司提供的异常类不足以描述不正常的情况,需要自定义。一般继承Exception、RuntimeException 即可。

// 自定义一个异常类
public class CustomException extends Exception {
    public CustomException(String message){
        super(message); // 将异常信息传递给父类
    }
}

// 使用:
public String getIP(String ip) throws CustomException{
    if (ip == null){
        throw new CustomException("没有ip...");
    }
    return ip;
}
// 测试方法中
try {
    new test().getIP("");

}catch (CustomException e){
    System.out.println("获取ip....");
}

finally 块:

finally块在任何情况下均执行,除了jvm退出的情况(system.exit(0)); 有无异常均执行。
使用前提:必须有try块才能使用。特别适合做资源释放工作,保证资源文件在任何情况下都会被释放、关闭流。

注意:
1、任何执行try 或者catch中的return语句之前(包括return后面的运算表达式),都会先执行finally语句,如果finally存在的话。
2、如果finally中有return语句,那么程序就return了,所以finally中的return是一定会被return的,编译器把finally中的return实现为一个warning。
3、finally是在try、catch块中return后面的表达式运算之后执行的,此时并没有返回运算之后的值,而是把值保存起来,不管finally对该值做任何的改变,try、catch块中返回的值都不会改变,依然返回保存起来的值。也就是说try、catch块中的返回值是在finally运算之前就确定了的。

举例:

情况 表达式 结果分析 ps
1 try{}catch{}finally{} return; 程序正常进行
2 try{return;}catch{}finally{} return; a、先执行try中的语句,包括return后面的表达式,b、然后执行finally中的语句,c、最后执行try中的return ps:返回值是try中的return后面的表达式的值,finally后面的return语句不会被执行
3 try{} catch{return;} finally{} return; 先执行try中的代码块 有异常:a、先执行catch中的语句,包括return后面的表达式,b、然后执行finally中的语句,c、最后执行catch中的return,finally后面的return不会被执行 无异常:执行finally中的代码块,然后执行return语句
4 try{return;} catch{} finally{return;} a、先执行try中的语句,包括return后面的表达式,b、然后执行finally中的语句,c、最后执行finally中的return 返回的值是finally中return后面的表达式的值,因为finally中有return语句,所以会提前退出
5 try{} catch{return} finally{return}; 先执行try中的代码块 有异常:a、先执行catch中的语句,包括return后面的表达式,b、然后执行finally中的语句,c、最后执行finally中的return,因为finally中有return语句,所以会提前退出 无异常:执行finally中的代码块,然后执行finally中的return finally中有return 会提前退出
6 try{return;} catch{return;} finally{return;} 先执行try中的代码块,包括return后面的表达式 有异常:a、先执行catch中的语句,包括return后面的表达式,b、然后执行finally中的语句,c、最后执行finally中的return,因为finally中有return语句,所以会提前退出 无异常:执行finally中的代码块,然后执行finally中的return finally中有return,try、catch中的return 无用。

Demo:

public String test(String str){
    try {
        //int i = 1/0;
        return str += "try";
    }catch (Exception e){
        return str += "catch";
    }finally {
        str += "finally";
        System.out.println("finally:" + str);
    }
}
// 测试:
public static void main(String[] args) {

    String test = new test().test("ron: ");
    System.out.println(test);
}
// 结果:
// 无异常:
finally:ron: tryfinally
ron: try
// 有异常:
finally:ron: catchfinally
ron: catch

结果分析参考上文注意的第三点。

你可能感兴趣的:(Java基础)