Java Exception
Java异常机制
在理想的情况下,我们的程序会按照我们的思路去运行,按理说是不会出现问题的,但是,代码实际编写后并不一定是完美的,可能会有我们没有考虑到的情况,如果这些情况能够正常得到一个错误的结果还好,但是如果直接导致程序运行出现问题了呢?
public static void main(String[] args) {
test(1, 0); //当b为0的时候,还能正常运行吗?
}
private static int test(int a, int b){
return a/b; //没有任何的判断而是直接做计算
}
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.test.Application.test(Application.java:9)
at com.test.Application.main(Application.java:5)
当程序运行出现我们没有考虑到的情况时,就有可能出现异常或是错误!
异常
我们在之前其实已经接触过一些异常了,比如数组越界异常,空指针异常,算术异常等,他们其实都是异常类型,我们的每一个异常也是一个类,他们都继承自Exception
类!异常类型本质依然类的对象,但是异常类型支持在程序运行出现问题时抛出(也就是上面出现的红色报错)也可以提前声明,告知使用者需要处理可能会出现的异常!
运行时异常
异常的第一种类型是运行时异常,如上述的列子,在编译阶段无法感知代码是否会出现问题,只有在运行的时候才知道会不会出错(正常情况下是不会出错的),这样的异常称为运行时异常。所有的运行时异常都继承自RuntimeException
,也就是说Exception类中除了RuntimeException类及其子类外都是编译时异常。
编译时异常
异常的另一种类型是编译时异常,编译时异常是明确会出现的异常,在编译阶段就需要进行处理的异常(捕获异常)如果不进行处理,将无法通过编译!默认继承自Exception
类的异常都是编译时异常。
处理编译时期异常有两种方式。具体如下:
-
使用try…catch语句对异常进行捕获
-
使用throws关键字声明抛出异常,调用者对其处理
-
注意throw和throws的区别
1)throws 关键字用于声明异常,它的作用和 try-catch 相似;而 throw 关键字用于显式的抛出异常。2)throws 关键字后面跟的是异常的名字;而 throw 关键字后面跟的是异常的对象。
示例。
throws ArithmeticException; throw new ArithmeticException("算术异常");
3)throws 关键字出现在方法签名上,而 throw 关键字出现在方法体里。
4)throws 关键字在声明异常的时候可以跟多个,用逗号隔开;而 throw 关键字每次只能抛出一个异常
File file = new File("my.txt");
file.createNewFile(); //要调用此方法,首先需要处理异常
checked exception 检查型异常
编译器要求你必须处置的异常,当你编写某段代码时,编译器要求你必须要对这段代码try…catch,或者throws exception。这种是编译器可以检查到的,通常都是由于与外部资源/网络交互而发生的,例如数据库问题、网络连接错误、文件丢失等问题。
checked异常的例子如:ClassNotFoundException,IOException,SQLException等。
抛出一个面试题:NoClassDefFoundError 和 ClassNotFoundException 有什么区别?
都是检查型的,也就是说需要throws或者try…catch
ClassNotFoundException
- 定义:
ClassNotFoundException
是一个受检异常(checked exception),表示在运行时无法找到指定的类。通常是在使用Class.forName()
方法动态加载类时抛出。 - 发生场景:当应用程序试图加载某个类,但该类在类路径中不可用时,会抛出此异常。
NoClassDefFoundError
- 定义:
NoClassDefFoundError
是一个错误(error),表示 JVM 在运行时找不到某个类的定义。这个错误通常发生在类被编译但在运行时不可用的情况下。 - 发生场景:当类在编译时存在,但在运行时无法找到该类的定义(例如,类文件被删除或类路径不正确),会抛出此错误。
代码示例
以下是一个示例,演示这两种异常的不同场景。
public class ClassLoadingExample {
// 这个方法尝试使用 Class.forName() 加载一个类
public static void loadClassDynamically(String className) {
try {
Class.forName(className);
System.out.println("Class " + className + " loaded successfully.");
} catch (ClassNotFoundException e) {
System.out.println("ClassNotFoundException: " + e.getMessage(