java异常处理
java异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的。
在程序出现异常的时候,我们可以选择抛出异常(throw)或者捕获异常(try catch),以控制程序的错误何时出现。
异常分类
- 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
- 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
- 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
Exception异常/Error错误类
结构
public class Exception extends Throwable {
static final long serialVersionUID = -3387516993124229948L;
/**
* Constructs a new exception with {@code null} as its detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*/
public Exception() {
super();
}
}
public class Error extends Throwable {
static final long serialVersionUID = 4980196508277280342L;
/**
* Constructs a new error with {@code null} as its detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*/
public Error() {
super();
}
}
可以看到Exception和Error是Throwable的两个派生类,而这两个类以下又有好多好多的派生类
非检查性异常
异常 | 描述 |
---|---|
ArithmeticException | 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。 |
ArrayIndexOutOfBoundsException | 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。 |
ArrayStoreException | 试图将错误类型的对象存储到一个对象数组时抛出的异常。 |
ClassCastException | 当试图将对象强制转换为不是实例的子类时,抛出该异常。 |
IllegalArgumentException | 抛出的异常表明向方法传递了一个不合法或不正确的参数。 |
IllegalMonitorStateException | 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 |
IllegalStateException | 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。 |
IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态时抛出的异常。 |
IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 |
NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常。 |
NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 |
NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 |
SecurityException | 由安全管理器抛出的异常,指示存在安全侵犯。 |
StringIndexOutOfBoundsException | 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 |
UnsupportedOperationException | 当不支持请求的操作时,抛出该异常。 |
检查性异常类
异常 | 描述 |
---|---|
ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出该异常。 |
CloneNotSupportedException | 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。 |
IllegalAccessException | 拒绝访问一个类的时候,抛出该异常。 |
InstantiationException | 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。 |
InterruptedException | 一个线程被另一个线程中断,抛出该异常。 |
NoSuchFieldException | 请求的变量不存在 |
NoSuchMethodException | 请求的方法不存在 |
异常方法
序号 | 方法及说明 |
---|---|
1 | public String getMessage() 返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。 |
2 | public Throwable getCause() 返回一个Throwable 对象代表异常原因。 |
3 | public String toString() 使用getMessage()的结果返回类的串级名字。 |
4 | public void printStackTrace() 打印toString()结果和栈层次到System.err,即错误输出流。 |
5 | public StackTraceElement [] getStackTrace() 返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。 |
6 | public Throwable fillInStackTrace() 用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。 |
异常捕获(try...catch)
在java中,我们使用try...catch进行异常的捕获,你需要捕获异常的代码块放在try里面,而需要捕获的异常需要写在catch里,并且在catch代码块中指定你需要如何解决这个异常。
语法:
try
{
// 程序代码
}catch(ExceptionName e1)
{
//Catch 块
}
我们先来引发一个异常:
public static void main(String[] args) {
int[] array = {1,2,3};
System.out.println(array[5]); // 数组下标越界
}
输出结果:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at day08.异常类.main(异常类.java:15)
接着来捕获以下这个异常,让他输出我们自定义的语句:
public static void main(String[] args) {
try{
int[] array = {1,2,3};
System.out.println(array[5]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("发生异常拉~");
}
}
输出结果:
发生异常拉~
可以看到我这里捕获的是ArrayIndexOutOfBoundsException,这是一种特殊的代表数组越界的异常,我们捕获特定的这种异常,当出现这种异常的时候就执行我们catch下的代码,假如发生了别的异常那么我们便捕获不到,如果想捕获所有异常,那么便直接catch(Exception e)即可。
那么假如我们想捕获多种异常要怎么实现呢?下面介绍一个东西
多重捕获
一个 try 代码块后面跟随多个 catch 代码块的情况就叫多重捕获。
多重捕获块的语法如下所示:
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}
实例:
public static void main(String[] args) {
try{
String s = "123abc";
Integer.valueOf(s);
int[] array = {1,2,3};
System.out.println(array[5]);
}catch (NumberFormatException e1){
System.out.println("发生类型转换异常拉~"); // 已经捕获到异常
}catch (ArrayIndexOutOfBoundsException e2){
System.out.println("发生数组下标越界异常拉~"); // 不进行捕获了
}
}
输出结果:
发生类型转换异常拉~
注意⚠️:假如有多重异常捕获的时候,只要有一个异常被catch到,那么其他的catch则不进行捕获了!假如第一个catch没捕获到异常,那么则依次进行下面的捕获。
throws/throw 关键字
我们有时候不想把异常捕获,或者想手动抛出一个异常,以告知我们的开发人员,程序出错拉!那么这个时候就需要利用到throws/throw关键字。
我们手动抛出一个异常看看
public static void test(){
throw new RuntimeException("手动抛一个异常!");
}
public static void main(String[] args) {
test();
}
输出结果;
Exception in thread "main" java.lang.RuntimeException: 手动抛一个异常!
at day08.异常类.test(异常类.java:14)
at day08.异常类.main(异常类.java:19)
throws关键字是在方法后面使用的,当一个检查性异常没有捕获的时候,我们可以在方法后面加上throws,我们称为“向上抛出异常”,如下
static void deposit(double amount) throws RemoteException {
// Method implementation
throw new RemoteException();
}
public static void main(String[] args) throws RemoteException {
deposit(2.2);
}
当你的IDE报红,除了语法错误以外,就是需要你对异常进行处理了,你可以选择try...catch或者throws,打个比方,try...catch就是负责任的好男人,自己做错了自己解决,而throws就是不负责任的渣男!自己犯的错让别人来处理!
finally关键字
在try...catch中,我们可以加上finally,finally就是不管你的程序发生了什么,finally中的代码都必须执行!并且是最后执行!
举个例子,在创建jdbc连接的时候,我们通常会在try中写上连接的代码,catch捕获连接异常,而finally则进行最后的操作,关闭数据库连接。
public static void main(String[] args){
try{
int[] array = {1,2,3};
System.out.println(array[5]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("发生异常拉~");
}finally {
System.out.println("最后执行finally代码");
}
}
输出结果:
发生异常拉~
最后执行finally代码
自定义异常
在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。
- 所有异常都必须是 Throwable 的子类。
- 如果希望写一个检查性异常类,则需要继承 Exception 类。
- 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
我们先来创建一个简单的自定义检查性异常:
class MyException extends Exception{
MyException(String msg){
super(msg); // 调用父类构造方法
}
}
在main方法中测试:
public static void main(String[] args) throws MyException {
throw new MyException("我的异常"); // 检查性异常必须加上throws关键字,不然编译报错
}
输出结果:
Exception in thread "main" day08.MyException: 我的异常
at day08.异常类.main(异常类.java:21)
接着再来创建一个运行时自定义异常:
class MyRuntimeException extends RuntimeException {
MyRuntimeException(String msg){
super(msg);
}
}
在main方法中测试:
public static void main(String[] args){
throw new MyRuntimeException("我的运行时异常"); // 运行时异常不需要throws
}
输出结果:
Exception in thread "main" day08.MyRuntimeException: 我的运行时异常
at day08.异常类.main(异常类.java:21)
以上就是关于异常处理的简单介绍。