java异常

基本概念

Java中的异常是指程序在运行时发生的不正常情况(开发过程中的语法错误和逻辑错误不是异常)。

异常类型

执行过程中所发生的异常可以分为两大类:

Error:

java虚拟机无法解决的严重问题,会导致程序直接崩溃

Exception:

因编程错误或偶然的外在因素导致的一般性问题,可以通过针对性的代码进行处理(如空指针访问,读取不存在的文件等)。同时Exception又可分为两大类:

[运行时异常]:

也称非检查型异常(Unchecked Exceptions)。是程序运行时发生的异常,特殊情况可不做处理(即交由系统默认处理方式处理)。例如空指针异常:(NullPointerException)当程序调用某对象并使用,但此时该对象为空时,系统就会抛出该异常:

java 复制代码
public class Go {
    public static void main(String[] args) {
        String str1="这是一句话";
        System.out.println(str1.length());
        //正常执行
        String str2=null;
        System.out.println(str2.length());
        //空指针异常
    }
}

[编译时异常]:

也称检查型异常(Checked Exceptions)编译器检查出的异常,必须要处理

关系表

java 复制代码
Throwable  
    |  
    +-- Error  
    |       |  
    |       +--VirtualMachineError  
    |       |       |  
    |       |       +--OutOfMemoryError  
    |       |       |  
    |       |       +-- ... (其他虚拟机错误)  
    |       |  
    |       +-- ThreadDeath  
    |       |  
    |       +-- ... (其他错误)  
    |  
    +-- Exception  
            |  
            +-- RuntimeException  
            |       |  
            |       +-- ArithmeticException  
            |       |  
            |       +-- NullPointerException  
            |       |  
            |       +-- IndexOutOfBoundsException  
            |       |  
            |       +-- ... (其他运行时异常)  
            |  
            +-- IOException  
            |       |  
            |       +-- FileNotFoundException  
            |       |  
            |       +-- ... (其他I/O异常)  
            |  
            +-- SQLException  
            |       |  
            |       +-- ... (SQL异常)  
            |  
            +-- ... (其他检查型异常)

异常处理

try-catch-finally

程序在代码中捕获发生的异常,自行处理(选中代码,按ctrl+alt+t快捷键可快速输入)

java 复制代码
try {  
    // 尝试执行的代码,可能会抛出异常  
} catch (ExceptionType1 e) {  
    // 当try块中抛出ExceptionType1类型的异常时执行的代码  
    //封装为对象e
} catch (ExceptionType2 e) {  
    // 当try块中抛出ExceptionType2类型的异常时执行的代码  
    // 可以有多个catch块来处理不同类型的异常  
} finally {  
    // 无论是否发生异常都会执行的代码  
    // 通常用于释放资源,如关闭文件、数据库连接等  
}
  • try块:包含可能抛出异常的代码。如果有异常,则执行相对应的catch块。
  • catch块:用于捕获try块中抛出的异常,并将其封装的新对象中。
  • finally块:无论是否发生异常,finally块中的代码都会被执行。

注意事项

1、如果try块中有异常发生,就会直接进入catch块,不会再继续向下执行try块中的其他语句;如果没有异常则不执行catch块。

java 复制代码
public class Go {
    public static void main(String[] args) {
        String str1="这是句话";
        String str2= null;

        try {//第一个try块
            System.out.println("str1长度:"str1.length());//正确,输出4
            System.out.println("无异常");//继续执行
        } catch (Exception e) {//因无异常,不再执行对应的catch块
            System.out.println("有异常发生");
        }

        try {//第二个try块
            System.out.println("str2长度:"str2.length());//错误,出现异常
            System.out.println("无异常");//不再继续执行
        } catch (Exception e) {//因有异常,直接执行对应的catch块
            System.out.println("有异常发生");
        }
    }
}

执行结果

字符串str1长度:4

无异常

有异常发生

2、可以有多个catch块,每个catch块捕获不同类型的异常,要求父类异常在后,子类异常在前。如果发生异常,只会匹配一个catch块。

java 复制代码
public class Go {
    public static void main(String[] args) {
        try {
            int num1 = 10;
            int num2 = 0;
            //将0作为除数,会导致算术异常
            System.out.println(num1 / num2);
//下例为空指针异常,在此仅作示例,不执行
//            A a = new A();
//            a = null;
//            System.out.println(a.getClass());
        } catch (NullPointerException e) {//第一个catch块
            System.out.println("空指针异常:" + e.getMessage());
        } catch (ArithmeticException e) {//第二个catch块
            System.out.println("算术异常:" + e.getMessage());
        } catch (Exception e) {//Exceptin为上两例异常的父类,因此放在后面
            System.out.println(e.getMessage());
        }
    }
}

执行结果:

算术异常:/ by zero

因为在该例中未发生空指针异常,所以第一个catch块不会被执行

3、因为finally块总会被执行的特性,所以其通常用于释放资源,如关闭文件、数据库连接等。也可以仅使用try-finally,这样无论程序是否异常,都会执行finally内的语句,但这种用法相当于未捕获异常,程序有可能崩溃。

throws

当方法内部使用了可能抛出异常的代码,并且这些方法不想或不能处理这些异常时,它们可以使用 throws 关键字来声明这些异常。这样,调用这个方法的代码就需要负责处理这些异常,或者继续向上层抛出。

如果该异常一直未被处理,系统就会调用主方法默认的 throws 方法输出异常信息。

声明异常

在声明方法时使用 throws 关键字,后面跟着一个或多个异常类型(用逗号分隔)。

java 复制代码
public void someMethod() throws SomeException, AnotherException {  
    // 方法体  
}

注意事项

thrwos后面的异常类型可以是方法中产生的异常类型,也可以是它的父类(如NullPointerException可以被替换成其父类Exception)。但注意抛出的异常类型要么和父类一致,要么为父类抛出的异常类型的子类型。

java 复制代码
class Father {//父类
    //父类方法抛出的异常类型为RuntimeException
    public void method()throws RuntimeException{}
}
class A extends Father{//子类A
    //正确、子类方法抛出的异常类型为RuntimeException和父类一致
    public void method() throws RuntimeException {
    }
}
class B extends Father{//子类B
    //错误、子类方法抛出的异常类型为RuntimeException的父类
    public void method() throws Exception {
    }
}

自定义异常

当程序中出现了某种异常,但该异常并未在系统所描述的异常类型中存在,这个时候我们就可以自己设计异常类,用于描述该异常信息。

声明异常

自定义异常类名继承自Exception或RuntimeException,并添加至少一个无参数的构造函数。如果继承自Exception则属于编译异常,如果继承自RuntimeException则属于运行异常(一般继承RuntimeException)。

java 复制代码
public class myE extends Exception {
    public E() {//添加构造函数
    //该异常所需执行的操作  
    }
}

例:判断某一变量的值是否处于1---100之间,如果不是,则抛出异常

java 复制代码
public class Go {
    public static void main(String[] args) {
        int num=101;
        if(!(num>=1&&num<=100))//判断该变量是否符合要求
            //抛出自定义异常MYE
            throw  new MYE("变量不在1-100之间");
        System.out.println("变量符合要求");
    }
}
//自定义一个异常
class MYE extends RuntimeException{//继承自RuntimeException,为运行异常
    public MYE(String message) {
        super(message);
    }
}

执行结果:

Exception in thread "main" pack.chn.class1.MYE: 变量不在1-100之间

at pack.chn.class1.Go.main(Go.java:10)

throw和throws的区别

不难注意到,上文分别出现了throw和throws,他们之间存在一定区别:

1、意义不同:throws是异常处理的一种方式,throw为自定义异常的关键字

2、位置不同:throws写在声明方法的语句中,throw则在方法体中

2、后续代码不同:throws后写的是异常类型,throw是异常对象

相关推荐
charlie11451419112 分钟前
如何使用Qt创建一个浮在MainWindow上的滑动小Panel
开发语言·c++·qt·界面设计
Dcs16 分钟前
VSCode等多款主流 IDE 爆出安全漏洞!插件“伪装认证”可执行恶意命令!
java
神仙别闹20 分钟前
基于Python实现LSTM对股票走势的预测
开发语言·python·lstm
保持学习ing21 分钟前
day1--项目搭建and内容管理模块
java·数据库·后端·docker·虚拟机
京东云开发者33 分钟前
Java的SPI机制详解
java
超级小忍1 小时前
服务端向客户端主动推送数据的几种方法(Spring Boot 环境)
java·spring boot·后端
程序无bug1 小时前
Spring IoC注解式开发无敌详细(细节丰富)
java·后端
小莫分享1 小时前
Java Lombok 入门
java
程序无bug1 小时前
Spring 对于事务上的应用的详细说明
java·后端
食亨技术团队1 小时前
被忽略的 SAAS 生命线:操作日志有多重要
java·后端