异常处理
Throwable类是所有异常和错误的超类.Error错误,Exception异常是他们的子类
错误(Error):OutOfMemoryError,LinkageError和StackOverflowError
异常分类:
受检时(checked)异常:也叫编译异常、非运行时异常,一般是非RunTimeException子类外的Exception类异常
非受检时(unchecked)异常:也叫非编译时异常、运行时异常,一般是RunTimeException类异常与Error类错误,这类异常一般不进行捕获,自行检查
(非受检的可抛出结构:运行时异常与错误,不要把可抛出结构与可抛出异常混淆)
常见运行时(RuntimeException)异常的子类异常:
1、 java.lang.ArrayIndexOutOfBoundsException
数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
2、java.lang.ArithmeticException
算术条件异常。譬如:整数除零等。
3、java.lang.NullPointerException
空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等
4、java.lang.ClassNotFoundException
找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。
5、java.lang.NegativeArraySizeException 数组长度为负异常
6、java.lang.ArrayStoreException 数组中包含不兼容的值抛出的异常
7、java.lang.SecurityException 安全性异常
8、java.lang.IllegalArgumentException 非法参数异常
9、 java.lang.IndeOutOfBoundException:试图使用一个超界的索引来引用一个对象
11、java.lang.InputMismatchException:输入类型异常
非运行时异常:
IOException:操作输入流和输出流时可能出现的异常。
EOFException 文件已结束异常
FileNotFoundException 文件未找到异常
其它异常:
ClassCastException 类型转换异常类
ArrayStoreException 数组中包含不兼容的值抛出的异常
SQLException 操作数据库异常类
NoSuchFieldException 字段未找到异常
NoSuchMethodException 方法未找到抛出的异常
NumberFormatException 字符串转换为数字抛出的异常
StringIndexOutOfBoundsException 字符串索引超出范围抛出的异常
IllegalAccessException 不允许访问某类异常
InstantiationException 当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常
异常的主要方法:
Throwable fillInStackTrace():返回一个包含调用栈信息的Throwable对象,该对象可以被重新抛出
String getCause():返回抛出异常的原因。如果 cause 不存在或未知,则返回 null。
void printStackTrace():将调用栈信息输出到标准错误,常用
String getMessage():返回对异常的描述
String getLocalizedMessage():返回对异常的本地描述
异常的捕获与处理:
显示异常:指执行对异常处理操作的是主体程序,主动将异常抛出,一般使用显示捕获,如使用throw方法
隐式异常:指执行异常处理操作的是JVM,异常抛出不受控制,一般使用隐式捕获,如try-catch-finally代码块,或者在其中使用throw方法
try{
可能异常的代码块
}catch(异常类型 异常变量名){
异常处理代码,可以是throw new ExceptionName("ERROR");
}finally{
无论是否异常都需要处理的代码 //最好是进行资源释放或关闭
}
注意:
1、如果异常类型与catch语句的异常不一致则直接终止运行;
2、允许多重catch语句进行异常捕获,且应先捕获特殊异常再捕获一般异常,捕获顺序从上到下,一旦匹配则不再执行其它语句;
3、try/catch/finally可以组成try…catch、try…catch、try…finally三种结构,catch语句块可以有一个或多个,finally语句块最多一个。另外try后紧跟catch语句,不能添加其它语句
4、try、catch、finally三个语句内的变量作用域为代码块内部。分别独立而不能相互访问,如需访问则需要将变量定义到这些语句内外部
5、finally语句在JVM中会被多次编译,对性能有影响
throws/&throw关键字:
即异常抛出给调用者而不处理
返回类型 方法名(参数类型 参数名) throws ExceptionName//显式声明异常,运行时异常不要求显式声明
{
.....
throw new ExceptionName("异常的信息")//抛出异常,一般前有判断语句
}
异常处理的一些经验:
1、finally代码块内切勿使用return语句,这样会破坏异常的正常处理与抛出,try语句中的return语句将不会执行,最好是进行内存释放、关闭IO与资源对象等操作
2、catch语句内最好执行相应的异常处理,不要忽视任何一个异常,空catch语句容易隐藏错误与异常
3、捕获具体的子类异常,而非Exception,throwable之类的,以防捕获到所有异常甚至是JVM抛出的无法处理的异常。
4、尽量减少异常捕获语句的使用,不要把异常处理语句当控制流程来使用,这样容易影响性能,如果需要使用请减少try语句内的代码,尽量精确定位
5、尽量将受检异常转化为运行时异常
6、注意正常的封装与传递异常
catch (SomeException e) {throw new MyException("Some information: " + e.getMessage()); //错误的做法}
catch (SomeException e) { throw new MyServiceException("Some information: " , e); //正确使用}
7、错误发生时及早抛出,然后在获得全部信息时再捕获处理.也可以理解为在低层次抛出的异常,在足够高的抽象层面才能更好的理解异常,然后捕获处理。
8、不要在finally语句中进行异常捕获操作,如果在finally中抛出异常,将会覆盖原始的异常,如果finally中真的可能会发生异常,那一定要处理并记录它,不要向上抛。
9、打印异常与处理异常二选一,不要都做
catch (SomeException e) { LOGGER.error("Some information", e); throw e;}//错误示范
,这样会打印一串的error log