1、java异常体系概述
java的异常体系如上图所示,主要分为两个部分:
- Error
- Exception
两者实现了同一个父类Throwable,只有继承Throwable的类和子类才能被抛出.
1.1.Error和Exception的区别?
Error类异常代表的是应用程序不应该catch捕获的异常,这类异常一般不是程序直接引起的,而是环境造成的.最常见的如:
- NoClassDefFoundError:运行时jvm加载不到类或找不到类
- OutofMemoryError: 内存溢出异常
Exception异常是程序应该catch捕获的异常.它包括RuntimeException(非检查异常)和非RuntimeException异常(检查异常),这类异常一般需要通过try-catch捕获或者通过方法throws到外部,让外部函数通过try-catch捕获.
常见的RuntimeException:
- NullPointerException :空指针异常
- ArrayIndexOutOfBoundsException: 数组越界异常
- ArithmeticException: 算术异常
- NumberFormatException: 数字格式异常
- ClassCastException: 类型转换异常.
这类异常一般编译器不会自动提示你try-catch,但是在程序运行时有可能会出现.
常见的检查异常:
- ClassNotFoundException: 找不到类异常
- SQLException: sql执行异常
- IOException: io过程读写文件异常.
这类异常需要手动try-catch或者在方法上throws抛出.
NoClassDefFoundError 和ClassNotFoundException的区别
jdk源码中对两者的定义如下:
NoClassDefFoundError是程序里面显示调用某一个类的静态方法或者执行new xxx()时,如果该类在当前classpath中找不到时,就会抛出该异常.
ClassNotFoundException:只有当ClassLoader通过一个类的权限定名字符串去加载类时,找不到对应的类文件,会报出该异常.
/**
* 当虚拟机或者ClassLoader 尝试加载类的定义文件并且当前类的定义文件找不到时,抛出异常
* 加载时机: 类的实例方法、静态方法被调用,通过new关键字创建实例
* Thrown if the Java Virtual Machine or a <code>ClassLoader</code> instance
* tries to load in the definition of a class (as part of a normal method call
* or as part of creating a new instance using the <code>new</code> expression)
* and no definition of the class could be found.
* <p>
* The searched-for class definition existed when the currently
* executing class was compiled, but the definition can no longer be
* found.
*
* @author unascribed
* @since JDK1.0
*/
public
class NoClassDefFoundError extends LinkageError {}
/**
* 当应用通过字符串名称加载类时,找不到对应类的定义文件,就会抛出异常.
*方法: Class.forName(""),ClassLoader中的findSystemClass/loadClass
*
* Thrown when an application tries to load in a class through its
* string name using:
* <ul>
* <li>The <code>forName</code> method in class <code>Class</code>.
* <li>The <code>findSystemClass</code> method in class
* <code>ClassLoader</code> .
* <li>The <code>loadClass</code> method in class <code>ClassLoader</code>.
* </ul>
* <p>
* but no definition for the class with the specified name could be found.
*
* <p>As of release 1.4, this exception has been retrofitted to conform to
* the general purpose exception-chaining mechanism. The "optional exception
* that was raised while loading the class" that may be provided at
* construction time and accessed via the {@link #getException()} method is
* now known as the <i>cause</i>, and may be accessed via the {@link
* Throwable#getCause()} method, as well as the aforementioned "legacy method."
*
* @author unascribed
* @see java.lang.Class#forName(java.lang.String)
* @see java.lang.ClassLoader#findSystemClass(java.lang.String)
* @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
* @since JDK1.0
*/
public class ClassNotFoundException extends ReflectiveOperationException {}
2.异常处理
2.1、Throw和Throws的区别
throws:
- 一般用在方法上,可以抛出多个异常,
- 抛出的异常不一定发生,只是提醒调用者,需要处理这些异常
throw :
- 一般用于抛出一个异常,用在方法内部,指定到throw时,一定会抛出异常.
2.2.try-catch-finally 和try-with-resources
2.2.1.try-catch-finally
使用说明:
public static void main(String[] args) {
System.out.println(testReturn());
}
public static int testReturn(){
try{
int i=1/0;
}catch (Exception e){
e.printStackTrace();
//1
return 0;
}finally {
System.out.println("a");
//2
return 1;
}
//3
return 2;
}
如上面代码所示:
- return语句:
- 如果方法中try-catch-finally
- 如果存在嵌套,那么会返回最外层的finally里面的return结果
- 如果finally中存在return语句,那么该finally之后不能出现任何代码,因为所有的逻辑到此就会结束
- 如果finally里面不存在return语句,当异常发生时
- 如果catch异常,则执行catch逻辑,如果有return语句,则在执行返回前,调用finally代码逻辑
- 如果catch异常逻辑中,屏蔽异常,则执行外层的返回逻辑
- 如果方法中try-catch-finally
- finally代码的执行逻辑
- 在try中代码或者catch中代码返回前执行
- finally只会在虚拟机已经退出时,不会执行,否则一定会执行
- 一般在finally逻辑中执行关闭连接、释放内存或其他资源的操作.
- catch的顺序
- catch逻辑可以存在多个,当捕获异常时,按照子类、父类顺序,先匹配子类异常,如果匹配成功,则执行对应的catch逻辑
- 如果存在多个catch逻辑,只会执行一个
2.2.2.try-with-resources
Try-with-resources是jdk1.7提供的功能,是针对try-catch-finally关闭资源编码方式的一种优化
使用如下:
try(FileInputStream in = new FileInputStream(new File(""))){
//使用in
}
需要自动关闭的资源如FileInputStream,必须实现AutoCloseable接口.