java中的异常(exception、throw、throws、try···catch)

 文章出处: https://blog.csdn.net/qq_33945246/article/details/89964438

 

 

一、throws 关键字
定义一个方法的时候可以使用 throws 关键字声明。使用 throws 关键字声明的方法表示此方法不处理异常,而交给方法调用处进行处理。使用 throws 抛出的运行时异常相当于提示调用者,该方法有风险,至于是否处理该风险,由调用者决定。

throws 关键字格式:

public 返回值类型 方法名称(参数列表,,,)throws 异常类 {};

二、throw 关键字
throw 关机字作用是抛出一个异常,抛出的时候是抛出的是一个异常类的实例化对象,

在异常处理中,try 语句要捕获的是一个异常对象,那么此异常对象也可以自己抛出。

try{
throw new Exception("自己抛着玩的。") ; // 抛出异常的实例化对象
}catch(Exception e){
System.out.println(e) ;
}
1
2
3
4
5
在主方法中的所有异常都可以不使用try…catch进行处理

三、在 JAVA 异常处理机制中,
1)如果抛出的是 EXception 的类型,则必须进行 try …catch 进行处理。

2)如果抛出的是 RuntimeException 的类型,则可以不使用 try。。catch 处理,一旦发生异常之后,将由 JVM 处理。

为了保证程序的健康性,在有可能出现异常的时候还是老实使用 try …catch 处理。

四、异常分类
Java 标准库内建了一些通用的异常,这些类以 Throwable 为顶层父类。

Throwable 又派生出 Error 类和 Exception 类。

错误:Error 类以及他的子类的实例,代表了 JVM 本身的错误。错误不能被程序员通过代码处理,Error 很少出现。因此,程序员应该关注 Exception 为父类的分支下的各种异常类。

异常:Exception 以及他的子类,代表程序运行时发送的各种不期望发生的事件。可以被 Java 异常处理机制使用,是异常处理的核心。

编译时异常必须显示处理,运行时异常交给虚拟机。
运行时异常可以不处理。当出现这样的异常时,总是由虚拟机接管。比如我们从来没有人去处理过 Null Pointer Exception 异常,它就是运行时异常,并且这种异常还是最常见的异常之一。出现运行时异常后,系统会把异常一直往上层抛,一直遇到处理代码。如果没有处理块,到最上层,如果是多线程就由 Thread.run () 抛出,如果是单线程就被 main () 抛出(此时main方法需要在方法签名中throws异常的种类)。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,整个程序也就退出了。运行时异常是 Exception 的子类,也有一般异常的特点,是可以被 Catch 块处理的。只不过往往不对它处理罢了。也就是说,如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。

五、异常处理的基本语法
在编写代码处理异常时,对于检查异常,有 2 种不同的处理方式:使用 try…catch…finally 语句块处理它。或者,在函数签名中使用 throws 声明交给函数调用者 caller 去解决。

实例:

A方法存在异常风险
main方法调用A方法

情况1:
A使用try-catch处理了异常,则main方法不需要做额外处理
情况2:
A在方法签名signature中throws了异常,此时main需要做出处理,有两种方式,第一就是使用try catch 捕获异常,另一种是在main方法签名中throws异常,jvm调用main方法,这是最后一层处理异常的机制了。

(一)

1、try 块中的局部变量和 catch 块中的局部变量(包括异常变量),以及 finally 中的局部变量,他们之间不可共享使用。

2、每一个 catch 块用于处理一个异常。异常匹配是按照 catch 块的顺序从上往下寻找的,只有第一个匹配的 catch 会得到执行。匹配时,不仅运行精确匹配,也支持父类匹配,因此,如果同一个 try 块下的多个 catch 异常类型有父子关系,应该将子类异常放在前面,父类异常放在后面,这样保证每个 catch 块都有存在的意义。

3、java 中,异常处理的任务就是将执行控制流从异常发生的地方转移到能够处理这种异常的地方去。也就是说:当一个函数的某条语句发生异常时,这条语句的后面的语句不会再执行,它失去了焦点。执行流跳转到最近的匹配的异常处理 catch 代码块去执行,异常被处理完后,执行流会接着在 “处理了这个异常的 catch 代码块” 后面接着执行。而try块中的异常后面的代码就不会在执行。
有的编程语言当异常被处理后,控制流会恢复到异常抛出点接着执行,这种策略叫做:resumption model of exception handling(恢复式异常处理模式 )
而 Java 则是让执行流恢复到处理了异常的 catch 块后接着执行,这种策略叫做:termination model of exception handling(终结式异常处理模式)

(二)
throws 函数声明

throws 声明:如果一个方法内部的代码会抛出检查异常(checked exception),而方法自己又没有完全处理掉,则 javac 保证你必须在方法的签名上使用 throws 关键字声明这些可能抛出的异常,否则编译不通过。

throws 是另一种处理异常的方式,它不同于 try…catch…finally,throws 仅仅是将函数中可能出现的异常向调用者声明,而自己则不具体处理。

采取这种异常处理的原因可能是:方法本身不知道如何处理这样的异常,或者说让调用者处理更好,调用者需要为可能发生的异常负责。

(三)
throw 异常抛出语句
throw exceptionObject

程序员也可以通过 throw 语句手动显式的抛出一个异常。throw 语句的后面必须是一个异常对象。

throw 语句必须写在函数中,执行 throw 语句的地方就是一个异常抛出点,它和由 JRE 自动形成的异常抛出点没有任何差别。

在一个语句块中,throw exceptionObject 后面不能跟任何代码
如果不是在try catch中,throw后面的代码都会执行,因为throw是抛出异常,一直向上抛出,直到遇到处理异常的代码,此时执行完catch的内容之后就会接着catch后面继续执行,因为java是 终结式异常处理模式

public static void main(String[] args) {
try {
abc();
} catch (Exception e) {
System.out.println("int the catch first");
e.printStackTrace();
System.out.println("in the catch last");
}
System.out.println("the last");

}

public static void abc() throws Exception {
System.out.println("1");

if (true) {
throw new Exception("异常");
}

System.out.println("2");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
执行结果:

1
int the catch first
java.lang.Exception: 异常
at test.exceptionTest.Test.abc(Test.java:21)
at test.exceptionTest.Test.main(Test.java:7)
in the catch last
the last
1
2
3
4
5
6
7
六、异常的注意事项
1、
当子类重写父类的带有 throws 声明的函数时,其 throws 声明的异常必须在父类异常的可控范围内 —— 用于处理父类的 throws 方法的异常处理器,必须也适用于子类的这个带 throws 方法 。这是为了支持多态。

例如,父类方法 throws 的是 2 个异常,子类就不能 throws 3 个及以上的异常。父类 throws IOException,子类就必须 throws IOException 或者 IOException 的子类。

2、
在 try 块中即便有 return,break,continue 等改变执行流的语句,finally 也会执行。

也就是说:try…catch…finally 中的 return 只要能执行,就都执行了,他们共同向同一个内存地址(假设地址是 0×80)写入返回值,后执行的将覆盖先执行的数据,而真正被调用者取的返回值就是最后一次写入的。

finally 中的 return 会覆盖 try 或者 catch 中的返回值。
finally 中的 return 会抑制(消灭)前面 try 或者 catch 块中的异常
finally 中的异常会覆盖(消灭)前面 try 或者 catch 中的异常

示例1:

public static String m1(){
try{
System.out.println("this is try method");

return "this is try return";
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println("this is finally method");

return "this is finally return";
}

}

public static void main(String[] args) {
System.out.println(m1());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
上述执行结果为:
this is try method
this is finally method
this is finally return

示例2:

public static String m1(){
try{
System.out.println("this is try method");

return "this is try return";
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println("this is finally method");

// return "this is finally return";
}

return "this is last return";
}

public static void main(String[] args) {
System.out.println(m1());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
执行结果为:
this is try method
this is finally method
this is try return

注:三个return 同时出现会编译错误

建议:
不要在 fianlly 中使用 return。
不要在 finally 中抛出异常。
减轻 finally 的任务,不要在 finally 中做一些其它的事情,finally 块仅仅用来释放资源是最合适的。
将尽量将所有的 return 写在函数的最后面,而不是 try … catch … finally 中。
————————————————
版权声明:本文为CSDN博主「温柔的谢世杰」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33945246/java/article/details/89964438

posted on 2020-07-02 16:59  头发渐秃终不悔  阅读(1629)  评论(0编辑  收藏  举报

导航