异常,根据字面理解,有意外之意。把它置于代码层面来理解,即阻止了当前方法或作用域继续执行。
异常的答题分类我画了一张图,可看下面的图
在上面这张图中可以看出,异常的基类是Throwable,它下面派生的Error和Exception,通常情况下,在对异常的理解的时候,我们一般只需要搞清楚以下这么几个问题就可以了:
1、Error和Exception有什么区别?
2、检查型异常 (CheckedException)和 非检查型异常 (UncheckedException)有什么区别?
以上两个问题在本篇博客的最后面解释。
ERROR 属于编译错误或系统错误,也属于严重错误,系统不可恢复,会导致系统终止运行 比如 OutOfMemoryError、NoClassDefFoundError
OutOfMemoryError是系统内存溢出,就是字面意思,系统内存不够用了。
这个异常的意思是在系统运行过程中找不到系统的class文件了,然后报此错误,所以我们如果想复现这个报错的话,可以在编译完成之后,在系统的运行过程中删除已经生成的class文件,然后再让系统去调用这个class文件,就会报NoClassDefFoundError异常。
RuntimeException(运行时异常),简单理解为在Java代码的运行过程中异常。
Java代码中在对null对象做操作的时候,抛出的异常。
就比如字符串“aa”转化成Int类型时报错,就会抛出ClassCastException (类型转换异常)。
比如说一个数组的下表最大是5,而代码中访问了6,抛出IndexOutOfBoundsException (越界异常)。
比如说代码中我们将一个字符串“33”要转成日期格式,就会抛出IllegalArgumentException (非法参数异常)错误,代码示例如下:
@Test public void illegalArgumentExceptionTest(){ String testTime = "33"; /** 格式化转换成我们想要的格式**/ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /** 格式化long类型的时间戳**/ String finalTime = sdf.format(testTime); System.out.println("你好:" + finalTime); }
在数组存值的时候,类型转换错误,代码示例如下:
@Test public void arrayStoreExceptionTest (){ Object[] array = new String[2]; array[1] = new Integer(1); }
由于在语法检查时,由于是Object类型的array,所以,语法检查不会报错,但是array内部是子类String类型实现的,所以在程序运行时,需要从Integer存储到String中,结果就会抛出 ArrayStoreException (数组存储异常)。
在进行数学计算时抛出的错误,代码示例如下:
@Test public void aruthmeticExceptionTest(){ int index = 1 / 0; }
代码示例如下:
@Test public void bufferOverflowExceptionTest(){ // 这里只分配了2个字节,下面的params.put(tmp);却put了3个字节的数据。所以导致 java.nio.BufferOverflowException 异常 ByteBuffer params = ByteBuffer.allocate(2); byte[] tmp = new byte[3]; tmp[0] = (byte) 1; tmp[1] = (byte) 8; params.put(tmp); }
non-RuntimeException(非运行时异常),意思就是不是Java代码运行过程的异常比如,在访问数据库的时候SQLException(数据脚本执行异常),超时时TimeoutException(超时异常),类没有找到时ClassNotFoundException(类未找到),以及IO异常IOException(IO异常),等等。
这里只需要记住两个名词,可预料、不可预料
Error和Exception都是继承于 Throwable 类,在Java中只有 Throwable 类才可以被抛出(throw)或者捕捉(try/catch)。
Error是不可预料的,这种异常发生之后,是不可恢复的,就比如,内存溢出错误(OutOfMemoryError)、类未定义错误(NoClassDefFoundError)。
Exception是可预料的,可以用try/catch捕捉到这种异常,然后抛出或者记录到日志中。
这里需要记住两个名词,可避免、不可避免
检查型异常和非检查型异常都属于Exception的分类下。
检查型异常是不可避免的,比如TimeoutException(超时异常)、IOException(IO异常)等,在方法上必须主动抛出。
非检查型异常是可避免的,比如NullPointerException (空指针异常)、 AruthmeticException (算术异常) 等这些是可以通过代码规范来避免的。