程序员就是不停的deBug,而这些Bug也就被我们称为异常。
了解异常
异常是为了预见在运行程序时可能会出现的问题,有问题安全退出程序的机制。所以的异常都有一个父类Throwable类,当然它也继承其他接口,但那个接口没有任何属性和方法。而Throwable又被两个类继承。分别是Error和Exception。
Error一般是编译器或虚拟机的问题,这个无解。我们能做的就是把编译器关闭后重新打开,严重的要重装JDK。
Exception也分为两类,一类是非运行时异常,另一类是运行时异常。
非运行时异常在编译时,编译器就可以提示我们,比如把整型赋值给字符串,少打符号或者中英的符号没区别开等等,编译器提示的错。
运行时异常,是我们编译运行后,进行该行代码运行时,出现了错误。比如:”ArithmeticException”、”ArrayIndexOutOfBoundsException”、”NullPointerException”等等等。这些都是我们常见的异常,算数异常、数组下标越界、空指针等等。而我们今天记录的就是提前发现运行时异常。
为啥学异常
当我们在处理数据时,尤其后面要学的流,很可能会出现很多错误,比如文件找不到,硬盘装不下,格式不匹配呀等等异常。很可能处理一行代码,就要做不断的判断。异常机制帮助我们,你做好开发就行,有问题交给Exception和它的子类去做。下面是简单的异常。
1 | public static void main(String[] args){ |
因为整数除以0,是无限大或无限小的数,无法表示的数,所以会报ArithmeticException异常,算数异常。我们可以提前预判,手动处理被除数是否为0。
而有些类或方法,必须要捕获异常和抛出异常,才能正常使用,否则编译器也会报错。这就是我们接下来学的异常,它属于运行时异常。
try-catch-finally
1 | try{ |
示例
1 | public static void main(String[] args){ |
从上面的运行结果可以看到,如果try里面的某行代码有异常,那么接下来的代码不会运行,直接进入到catch里。
而且,catch是可以多个使用,因为我们try不可能只写一个代码,可能有多个代码会出现不同的异常。
这catch里的异常怎么写也有讲究,如果是同一级的子类,顺序可以随意,但如果有父类异常,一定要写在子类后面。原因有两,一,子类更能详细异常的问题,二,catch是从上到下执行的,全让父类执行了,那之后的子类也没必要了。
只要写了finally,那它可能就是最后执行的。因为它也会有例外。
1 | public static void main(String[] args){ |
上面这段代码,在plus方法里,catch执行了return -1语句,但并没有结束运行,打印-1。而是继续运行到finally执行return 1.所以最后打印1。所以return也不能阻止finally的运行。但是,看下面。
1 | public static void main(String[] args){ |
而在上面这段代码中,打印“执行catch了吗”,System.exit(0)是直接退出程序。所以没运行到finally。我们写代码要避免使用System.exit(0)的使用。
throws
当然,还有就是甩锅式的抛出异常,我不处理异常,交给上一级处理吧,而上一级可能也不处理异常,也抛了出去,直到抛给了Object类处理异常,它的使用很简单。在方法名后加Throws 和异常名就行。
1 | public static void main(String[] args) throws Exception,NullPointerException{} |
自定义异常
可能有的时候,异常类里面并没有解决我们的错误,需要我们自己写异常。
1 | public class ThrowableTest { |
异常以后会常伴在我们左右,所以写代码一定要注意。