Java—异常Exception
什么是异常
异常是在程序执行期间发生的事件,它会打断正常的程序指令流程
在Java中有异常类专门来记录不同的异常,他们继承于Throwable类,如下图所示:
Error表示系统级错误,系统一旦出问题sun公司会把错误封装成Error对象,以便内部人员排查;
RuntimeException表示运行时异常,比如我们常见的数组越界访问、空指针异常等等,还有另一类是编译时期异常,必须要在编译时期就要处理掉,它的本质是为了提醒程序员检查本地信息,如果不注意就会出现异常,而不是像运行时期异常那样实实在在的出现错误,因此编译时期的异常我们都需要提前处理,避免真的报错;比如 IOException 表明正在处理IO流(读写文件操作),可能会发生异常,这个时候编译器就会提醒我们要将这个异常抛出或者try-catch,避免在运行的时候真的报错,从而阻值程序正常运行;
怎么处理异常
1.虚拟机默认处理异常
也就是程序员不做任何处理,出现的异常虚拟机会在控制台进行输出,然后终止程序的运行(其实就是我们经常见的异常的方式)
2.使用try-catch来捕获异常
使用try-catch代码块来捕获异常并处理,好处是可以让代码继续往下执行,不会像虚拟机那样终止程序
public static void main(String[] args) {int[] arr = {1,2,3,4,5};try {System.out.println(arr[10]);} catch (ArrayIndexOutOfBoundsException e){System.out.println("数组越界了");}System.out.println("看看我执行了吗");}
使用try{}来括住可能会出现异常的代码,然后使用catch来捕获可能会出现异常并处理,上面的例子中try里的arr[10]是越界访问了,然后在catch中捕获了ArrayIndexOutOfBoundsException(数组越界异常)并做了输出
需要考虑的四个问题:
- 如果try中没有遇到问题该怎么执行?
如果没有遇到问题,那么就不会执行catch里的代码,其余正常顺序执行
- 如果try中遇到多个问题该怎么执行?
为了应对出现的多种异常,我们需要多写几个catch,来分别对应不同的异常,但是遇到下面这种情况
public static void main(String[] args) {int[] arr = {1,2,3,4,5};try {System.out.println(arr[10]);System.out.println(2/0);} catch (ArithmeticException e) {System.out.println("除数不能为0");} catch (ArrayIndexOutOfBoundsException e){System.out.println("数组越界了");}System.out.println("看看我执行了吗");}
在try中同时出现两个问题,那么它执行的顺序是先执行sout(arr[10]),然后出现数组越界异常,之后被第二个catch捕获,输出sout("数组越界了"),try-catch执行完之后输出sout("看看我执行了吗")并没有发生sout(2/0)这行代码的异常捕获
- 如果try中的问题没有被捕获该怎么执行?
比如try中出现了算数异常(除数为0的情况),但是catch并没有对应的异常捕获代码,那么就会交由虚拟机来进行异常处理
- 如果try中遇到问题,那么try下面的代码还执不执行?
try下面的代码不会执行了,就如同第二个问题里说的一样,sout(2/0)就不会执行了
3.抛出异常
有throws、throw两个关键字,其中throws关键字是跟在方法定义后面的,用来表明执行该方法的时候可能会出现某种异常,通常我们会将编译时异常使用throws抛出,而运行时异常一般没必要抛出,因为一旦在运行的时候报错,那么虚拟机会自己处理或者我们使用上面说的try-catch方法来处理,所以抛或者不抛,该异常都会被处理。
public void getMessage() throws IOException{System.out.println("执行该方法的时候可能会出现IO异常");}
throw是在方法体中用于抛出异常,交给调用者来处理,然后该方法之后的代码就会终止运行,如下所示:
public void getMessage(String name){if ("".equals(name)){throw new RuntimeException();}System.out.println("我就不会执行了");}
name一旦为null,该方法就会抛出RuntimeException,然后该方法下面的打印语句就不会再执行了,如果方法外部没有try-catch或者全局异常处理,那么就会交给虚拟机来处理异常。
自定义异常
Java提供的异常类数量有限,为了能更好的描述我们所遇到的错误,可以自定义异常类
1.首先得继承RuntimeException/Exception类
如果是自定义的运行时异常,那么继承RuntimeException即可,如果是自定义编译时异常,那么继承Exception即可
2.空参构造和有参构造
public class MyException extends RuntimeException{public MyException() {}public MyException(String message) {super(message);}
}
以上就是一个最简单的自定义异常类,使用的时候通过throw抛出即可,如下所示:
public void getMessage(String name){if ("".equals(name)){throw new MyException();}System.out.println("我就不会执行了");}
需要注意的是,如果我们继承的是Exception,也就表明这是自定义的编译时异常,那么在使用的时候,需要在类或者方法定义之后通过throws抛出,表明该方法可能会遇到这个编译时的异常。