return,返回。return跳出的是方法体,
异常的概述
Java 中的异常(Exception)又称为例外,是一个在程序执行期间发生的事件,它中断正在执行程序的正常指令流。 任何人都无法保证程序永远准确运行,程序一旦出现异常,那么就像现实中碰到异常问题一样,需要得到及时的处理。
异常处理是程序设计中一个非常重要的方面,也是程序设计的一个难点。即使你感觉自己写的程序是相当的棒,但在运行时还是有可能会出现意外的情况。
异常的分类
Throwable类是Java语言中所有错误或异常的超类,这意味着只要是错误或者异常,那么肯定是Throwable子类的实例,但是事实上,由于错误,异常内容过于庞大,所以设计人员将他们分开来,这就是Throwable的两个子类,Error和Exception
Error类负责错误,它指程序运行的时候遇到硬件或操作系统的错误,如内存溢出,堆栈溢出,动态链接错误,虚拟机JVM错误等,这些错误都是严重并且致命的,是依靠程序自身无法解决的
Exception则是运行时的错误,它可以被捕获并处理
Exception又分为两大类:
运行时异常都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般由程序逻辑错误引起,程序应该从逻辑角度尽可能避免这类异常的发生。
非运行时异常是指RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、ClassNotFoundException等以及用户自定义的Exception异常
常见的异常
异常 | 备注 |
RuntimeException | Java.lang包中多数异类的基类 |
ArithmeticException | 算数错误,除数为0 |
ArraylndexOutOfBoundException | 数组大小小于或大于实际的数组大小 |
ClassNotFoundException | 不能加载所需的类 |
NumberFormatException | 从字符串到数据类型的非法转换 |
NullPointerException | null指针异常 |
FileNotFoundException | 文件没有找到 |
IOException | IO异常 |
InterruptedException | 线程中断 |
方法接收到非法参数 | |
ClassCastException | 类型转换异常 |
SQLException | SQL数据库异常 |
异常的处理
捕获异常
Java异常处理通过5个关键字控制:try,catch,throw,throws和finally,捕获异常使用try…catch语句,把可能发生异常的代码放到try {…}中,然后使用catch捕获对应的Exception及其子类:
try{
会出现异常的代码
}catch(异常类型 给异常起的变量名){
此处捕获到括号里异常类型后的做法
异常变量名. printStackTrace();(打印输出异常信息,可有可无)
}
1 | try{ //要监控是否有异常的代码 //代码A //代码B }catch(ExceptionType et1){ //对异常1进行处理 }catch(ExceptionType et2){ //对异常2进行处理 }finally{ //try模块结束前必须执行的代码块 } |
try catch
1 | Scanner input = new Scanner(System.in); |
多catch
1 | Scanner input = new Scanner(System.in); try{ 会出现异常的代码 }catch(异常类型 给异常起的变量名){ 此处捕获到括号里异常类型后的做法 异常变量名. printStackTrace();(打印输出异常信息,可有可无) } catch(异常类型 给异常起的变量名){ 此处捕获到括号里异常类型后的做法 异常变量名. printStackTrace();(打印输出异常信息,可有可无) } |
嵌套try catch(和嵌套for循环 使用哪个方法一样)
1 | Scanner input = new Scanner(System.in); |
finally关键字
有些时候,try块内引用了一些物理资源,例如数据库连接,网络连接或磁盘文件等。那么一旦try块内出现了异常,这些资源将无法保证可以释放。这时候我们是不是可以把资源释放的处理放在catch中执行呢?当然是不可以的,因为catch操作很可能不会被执行,如果没有发生异常,那么就不会有资源释放的操作了。所以必须有一种可以明确保证资源一定得到释放的操作,不管是否存在异常,这就是finally存在的原因。
1 | Scanner input = new Scanner(System.in); try{ 会出现异常的代码 }catch(异常类型 给异常起的变量名){ 此处捕获到括号里异常类型后的做法 异常变量名. printStackTrace();(打印输出异常信息,可有可无) } catch(异常类型 给异常起的变量名){ 此处捕获到括号里异常类型后的做法 异常变量名. printStackTrace();(打印输出异常信息,可有可无) }finally{ 不管是否出现异常;这个地方内的代码一定会被执行 一般是回收资源 例如:sc.close(); 关闭输入资源 } |
抛出异常
在Java系统中,我们不仅可以使用try-catch来捕捉异常,还可以使用throw语句来显式的引发异常,执行的代码一旦遇到throw语句,就会立即停止,不会继续往后执行。其语法为:
1 | throw <Throwable instance> |
实例:
1 | public static void main(String[] args) { |
throw
throw是显示的抛出一个异常,一般是在代码块的内部,当程序出现某种逻辑错误时由程序员主动抛出特定类型的异常
throws
throws是方法可能抛出异常的声明,用在声明方法时,表示该方法可能抛出异常,然后交给上层调用它的方法处理
区别
throw出现在方法体,throws出现在方法头
throw是抛出了异常,执行throw则一定是抛出了某种异常,throws是表示出现异常的一种可能性,并不一定会抛出这些异常
自定义异常
当我们在代码中需要抛出异常时,尽量使用JDK已定义的异常类型,在一些大型项目中,可能需要自定义新的异常类型,但是,保持一个合理的异常继承体系是非常重要的。
一个常见的做法是自定义一个BaseException作为“根异常”,然后,派生出各种业务类型的异常。
BaseException需要从一个适合的Exception派生,通常建议从RuntimeException派生:
1 | public class BaseException extends RuntimeException { |
其他业务类型的异常就可以从BaseException派生:
1 | public class UserNotFoundException extends BaseException { |
自定义的BaseException应该提供多个构造方法:
1 | public class BaseException extends RuntimeException { |