异常
异常
- java异常结构中定义有Throwable, Exception 和 Error 是其派生的两个子类。
- 其中Exception表示由于网络故障,文件损坏,设备错误,用户输入非法等情况导致的异常,而Error表示java运行时环境出现的错误,例如jvm内存资源耗尽。
- 异常出来就是当异常发生的时候妥善地终止程序,避免灾难性后果的发生,具体的操作通常包括;
通知:向用户通知异常的发生。
恢复:保存重要的数据,恢复文件, 回滚事务等
退出:以更好的方式结束程序的运行
“throw”、"throws"和"try…catch"是处理异常的三种不同方式、他们的区别
1. throw:
"throw" 是关键词,用于在代码中手动抛出一个异常。
当程序中某个地方发生了异常情况,并且需要在代码中明确指定该异常时,可以使用 throw 关键词。
可以通过 throw 抛出 Java 内置的异常类,也可以自定义异常类并抛出。
throw 是用在方法内部,用于明确指明出现的异常情况,并抛出异常给方法的调用者处理。
throw new XXException();
throw之后的代码不能执行到
2. throws:
"throws" 是关键词,用于在方法声明中声明可能会抛出的异常列表。throws 后面跟着异常类型,可以声明多个异常类型,使用逗号分隔。
当一个方法执行可能抛出某种类型的异常时,可以使用 throws 关键词在方法声明中指定该异常。那么在调用方法的时候,就需要捕获异常,或者继续抛出异常。
public void add() thows XXExcedption{
// code
}
throws 是用在方法声明上,用于告诉方法的调用者在调用此方法时需要处理指定的异常类型。在方法中,可以通过 throw 抛出异常。
throw 和 throws 不会处理异常,它们只是将异常传递给方法的调用者或抛出到方法的调用堆栈中。
3. try…catch:
"try…catch" 是异常处理的语句块。它用于捕获和处理异常。
try…catch 语句块用于捕获并处理已知的异常,以防止程序崩溃,并提供异常情况的适当处理。
在 try 块中,放置可能会发生异常的代码;在 catch 块中,指定要捕获和处理的异常类型,以及相应的处理逻辑。如果在 try 块中发生异常,程序将跳转到与之匹配的 catch 块,而不会导致程序终止。如果try块没有发生异常,那么所有的catch语句都被忽略,不被执行
可以有多个 catch 块来捕获不同类型的异常。当由多个catch语句的块时,应该先捕获小类型的异常,在捕获大类型的异常
try…catch 可以处理异常,并提供相应的处理逻辑,以便程序能够继续执行
使用场所:
- 使用 throw 时,适用于在方法内部检测到错误或异常情况,并明确指定要抛出的异常,将异常传递给方法的调用者处理。
- 使用 throws 时,适用于方法声明中声明可能会抛出的异常,要求方法的调用者对这些异常进行处理或转发。
- 使用 try…catch 时,适用于捕获和处理可能会发生的异常,以避免程序的崩溃,并提供相应的异常处理逻辑。
finally语句块
finally语句为异常处理提供一个统一的出口,使得在控制流程转到其他程序其他部分之前,能够对程序的状态做统一管理。
无论try语句块中是否有异常,finally语句块的内容都会被执行。
通常在finally语句块中完成一些必须要执行的代码。比如: 文件的关闭,数据库的关闭等。
自定义异常类
将自定义异常类定义为继承自Java内置的Exception
类或其子类,可以帮助异常处理机制捕获、处理和传播异常。自定义异常类通常包含以下几个重要部分:
- 类名:自定义异常类的名称应该反映出异常类型的含义,通常以
Exception
结尾,例如MyCustomException
。 - 构造方法:自定义异常类应该提供至少一个构造方法,以便在抛出异常时传递异常消息或其他必要的参数。可以使用
super
关键字调用父类的构造方法。 - 异常信息:通过在自定义异常类中添加成员变量或方法,可以提供有关异常的详细信息。例如,添加一个成员变量来存储错误代码或异常原因,或添加一个方法来获取异常的更多上下文信息。
下面是一个示例,演示如何创建一个自定义异常类:
public class MyCustomException extends Exception {
private int errorCode;
public MyCustomException(String message, int errorCode) {
super(message);
this.errorCode = errorCode;
}
public int getErrorCode() {
return errorCode;
}
}
在上面的示例中,
MyCustomException
是一个继承自Exception
类的自定义异常类。它包含了一个名为errorCode
的成员变量,用于存储异常的错误代码。构造方法接受异常消息和错误代码作为参数,并调用父类的构造方法来设置异常消息。getErrorCode
方法用于获取错误代码。
在实际应用中,可以使用自定义异常类来抛出和处理特定的异常情况。例如:
public class MyClass {
public void doSomething() throws MyCustomException {
// 某些操作
if (/* 某种异常情况 */) {
throw new MyCustomException("发生自定义异常", 1001);
}
// 其他操作
}
}
public class Main {
public static void main(String[] args) {
try {
MyClass obj = new MyClass();
obj.doSomething();
} catch (MyCustomException e) {
System.out.println("捕获自定义异常:" + e.getMessage());
System.out.println("错误代码:" + e.getErrorCode());
}
}
}
在上面的例子中,当
doSomething
方法中发生某种异常情况时,会抛出自定义异常MyCustomException
。在Main
类的main
方法中,通过使用try-catch
块捕获并处理该异常,打印异常消息和错误代码。
重写异常处理
在Java中,重写异常处理是指在子类中覆盖父类中定义的异常处理机制。当子类覆盖父类方法时,子类可以更改方法的异常处理,包括抛出新的异常、抛出父类异常的子类异常,或者不抛出异常。
在Java中,异常处理通过使用try-catch块来处理可能发生的异常。在父类方法中,可以使用try-catch块来捕获异常,处理异常或将异常传递给调用者。然而,子类可以重写父类的方法,并覆盖父类的异常处理机制。
1. 抛出新的异常:
子类可以在方法中抛出一个完全不同的异常。这需要子类方法的throws子句中声明新的异常类型,且新的异常类型必须是父类异常类的子类。这样做的好处是可以提供更具体的异常信息,并允许调用者有更好的针对异常情况的处理。
class Parent {
void method() throws IOException {
// 父类方法抛出IOException异常
}
}
class Child extends Parent {
void method() throws FileNotFoundException {
// 子类方法抛出FileNotFoundException异常(IOException的子类)
}
}
2. 使用父类异常的子类异常:
子类可以抛出父类异常的任何子类异常。这样做不会改变方法签名,但允许抛出更具体的异常。调用者可以根据抛出的异常类型进行适当的异常处理。
class Parent {
void method() throws IOException {
// 父类方法抛出IOException异常
}
}
class Child extends Parent {
void method() throws FileNotFoundException {
// 子类方法抛出FileNotFoundException异常(IOException的子类)
}
}
3. 不抛出异常:
子类方法还可以选择不抛出任何异常。这意味着子类方法不会产生异常,即使父类方法定义了异常处理机制。这在特定情况下可能是有意义的,例如,如果子类中的处理逻辑可以确保不会引发异常。
class Parent {
void method() throws IOException {
// 父类方法抛出IOException异常
}
}
class Child extends Parent {
void method() {
// 子类方法不抛出异常
}
}
通过重写异常处理,子类可以自定义异常处理逻辑,提供更详细的异常信息,并允许调用者更灵活地处理异常情况。根据实际需求和设计准则,可以选择抛出新的异常、使用父类异常的子类异常或不抛出异常。
常见异常
-
NullPointerException(空指针异常):当代码尝试使用空对象引用调用方法或访问字段时抛出。
-
ArrayIndexOutOfBoundsException(数组索引越界异常):当指定的数组索引超出有效范围时抛出。
-
ArithmeticException(算术异常):当算术运算中发生错误时抛出,如除以零或溢出。
-
IllegalArgumentException(非法参数异常):当传递给方法的参数不合法或无效时抛出。
-
ClassCastException(类转换异常):当试图将对象强制转换为不兼容的类时抛出。
-
StackOverflowError(栈溢出异常):当递归方法或函数调用层次过多导致栈空间耗尽时抛出。
-
IOException(输入输出异常):当操作输入/输出流失败或中断时抛出。
-
FileNotFoundException(文件未找到异常):当试图打开不存在的文件时抛出。
-
InterruptedException(中断异常):当线程处于等待、睡眠或被中断状态时发生中断时抛出。
-
UnsupportedOperationException(不支持的操作异常):当对象不支持请求的操作时抛出。
-
NumberFormatException(数字格式异常):当字符串无法转换为数字类型时抛出。
-
StringIndexOutOfBoundsException(字符串索引越界异常):当指定的字符串索引超出范围时抛出。
-
NoSuchMethodException(方法未找到异常):当试图调用不存在的方法时抛出。
-
SecurityException(安全异常):当安全性限制被违反时抛出。
-
NullPointerException(空指针异常):当代码尝试使用空对象引用调用方法或访问字段时抛出。
-
IllegalArgumentException(非法参数异常):当传递给方法的参数不合法或无效时抛出。
-
IllegalStateException(非法状态异常):当对象在调用方法之前或之后处于无效状态时抛出。
-
ConcurrentModificationException(并发修改异常):当在迭代集合对象时,该对象的结构被修改而导致的异常。
-
ClassNotFoundException(类未找到异常):当无法找到类的定义时抛出。
-
OutOfMemoryError(内存溢出错误):当JVM内存不足以分配新对象时抛出。