JavaSE笔记08异常

本文详细介绍了Java中的异常处理,包括检查性异常、运行时异常和错误的分类,以及异常处理机制如try-catch-finally和throws的使用。强调了编译时异常与运行时异常的区别,并提供了自定义异常的示例。最后分享了实际开发中的异常处理经验和注意事项,提倡合理规避和处理异常,确保程序的稳定性和健壮性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异常Exception

  1. 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
  2. 异常发生在程序运行期间,它影响了正常的程序执行流程
简单分类

要理解java异常是如何工作的,需要掌握以下三种类型的异常

  1. 检查性异常:最具代表性的异常是用户错误或问题引起的异常,这是程序员无法预见的,例如要打开一个不存在的文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
  2. 运行时异常:运行时异常是可能被程序员避免的异常,与检查性异常相反,运行时异常可以在编译时被忽略。
  3. 错误Error:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译时也检查不到的。
异常体系结构
  1. java把异常当做对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类
  2. 在jJava API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception
Error

Error类对象由java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关

java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,java虚拟机(JVM)一般会选择线程终止

Exception

在Exception分支中有一个重要的子类RuntimeException(运行时异常)

  1. ArrayIndexOutOfBoundsException(数组下标越界)
  2. NullPointerException(空指针异常)
  3. ArithmeticException(算术异常)
  4. MissingResourceException(丢失资源)
  5. ClassNotFoundException(找不到类)

这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生

Exception下有两个分支:

  1. Exception的直接子类:编译时异常,(要求程序员在编写程序阶段必须预先对这些异常进行异常处理,如果不处理编译器会报错,因此得名编译时异常)

  2. RuntimeException:运行时异常,(在编写程序阶段程序员可以预先处理,也可以不管,都行)

Error和Exception的区别
  1. Error通常是灾难性的致命错误,是程序无法控制和处理的,当出现这些异常时,java虚拟机(JVM)一般会选择终止线程
  2. Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常
编译时异常和运行时异常的区别:
  1. 编译时异常一般发生的概率比较高,对于一些发生概率较高的异常,需要在运行之前对其进行预处理。

  2. 运行时异常一般发生的概率比较低,这种发生概率较低的异常进行预处理,如果处理这种异常,将活得很累。

异常处理机制

java语言中对异常的处理包括两种方式

  1. 在方法声明的位置上,使用throws关键字,抛给上一级。谁调用我,我就抛给谁,抛给上一级

    注意:异常发生后如果一直上抛,最终抛给了main方法,main方法继续向上抛,抛给了调用者JVM,JVM知道这个异常发生,只有一种结果,终止java程序的执行。

package com.exception;

public class Test {
    public static void main(String[] args){

        try {
            new Test().test(1,0);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }
    }
    //假设这方法中,处理不了异常,方法向上抛出异常
    public void test(int a,int b) throws ArithmeticException{
        if(b == 0){
            throw new ArithmeticException();//主动抛出异常,一般在方法中使用
        }
        System.out.println(a / b);
    }
    /*
    运行结果:java.lang.ArithmeticException
     */
}
  1. 使用try…catch语句进行异常的捕捉,这件事发生了,谁也不知道,因为我给抓住了。
package com.exception;

public class Test {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;

        System.out.println(a/b);
        //Exception in thread "main" java.lang.ArithmeticException: / by zero
    }
}

捕获异常如下:

package com.exception;

public class Test {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;

        try {//try监控区域
            System.out.println(a/b);
        } catch (ArithmeticException e){//catch 捕获异常
            //e.printStackTrace();//打印异常追踪的栈堆信息
            System.out.println("处出现异常,变量b不能为0");//这里是自己写的错误提示信息
        } finally {//处理善后工作,一定会执行的
            System.out.println("finally");
        }
        /*
        运行结果:处出现异常,变量b不能为0
                 finally
         */
    }
}

快捷键:Ctrl + Alt + T

  1. 选中会发生错误的代码,如这里是System.out.println(a/b);按Ctrl + Alt + T弹出选项窗口
  2. 选择 try/finally 或者 try/catch/finally 回车即可

对比:

public class ExceptionTest05 {
    //第一种处理方式:在方法声明的位置上继续使用:throws,来完成异常的继续上抛,抛给调用者
    //上抛类似于推卸责任(继续把异常上抛传递给调用者)
    /*
    public static void main(String[] args) throws ClassNotFoundException{
       doSome();
    }
    */

    //第二种处理方式:try...catch进行捕捉
    //捕捉等于把异常拦下了,异常真正解决了(调用者是不知道的)
    public static void main(String[] args) {
        try {
            doSome();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void doSome() throws ClassNotFoundException{
        System.out.println("doSome!!!");
    }
}

在以后的开发中,处理编译时异常,应该上报还是捕捉呢?

  1. 如果希望调用者来处理,选择throws上报。
  2. 其他情况使用捕捉的方式。
深入try…catch
  1. catch后面的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型
  2. catch可以写多个,建议catch的时候,精确的一个一个处理,这样有利于程序的调试
  3. catch写多个的时候,从上到下,必须遵守从小到大

异常对象有两个非常重要的方法:

  1. 获取异常简单的描述信息:String msg = exception.getMessage();

  2. 打印异常追踪的栈堆信息:exception.printStackTrace();

public class ExceptionTest08 {
    public static void main(String[] args) {
        //这里只是new了异常对象,没有将异常对象抛出,JVM会认为这是一个普通的java对象
        NullPointerException e = new NullPointerException("空指针异常");
        //获取异常简单描述信息,这个信息实际上就是构造方法上面的String参数
        String msg = e.getMessage();//空指针异常
        System.out.println(msg);
        //打印异常堆栈信息
        //java后台打印异常堆栈追踪信息的时候,采用了异步线程的方式打印的
        e.printStackTrace();
        System.out.println("Hello World!");
    }
}
/*
运行结果:
	空指针异常
	Hello World!
	java.lang.NullPointerException: 空指针异常
*/

自定义异常

java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需要继承Exception或RuntimeException类即可。

大体可分为以下几个步骤:

  1. 创建自定义异常类
  2. 在方法中通过throw关键字抛出异常对象
  3. 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
  4. 在出现异常方法的调用者中捕获并处理异常
package com.exception;

//自定义的异常类
public class Demo02 extends Exception {

    //传递数字 > 10;
    private int detail;

    public Demo02(int a) {
        this.detail = a;
    }
    //toString,常的打印信息
    @Override
    public String toString() {
        return "Demo02{" + + detail + '}';
    }
}
package com.exception;

public class test02 {
    //可能会存在异常的方法
    static void test02(int a) throws Demo02 {

        System.out.println("传递的参数为:" + a);

        if (a > 10){
            throw new Demo02(a);//抛出
        }
        System.out.println("OK,End!");
    }

    public static void main(String[] args) {
        try {
            test02(11);
        } catch (Demo02 demo02) {
            System.out.println("Demo02=>" + demo02);
        }
        /*
        运行结果:
            传递的参数为:11
            Demo02=>Demo02{11}
         */
    }
}

实际应用中的经验总结

  1. 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
  2. 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
  3. 对于不确定的代码,也可以加上try-catch,处理潜在的异常
  4. 尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输出
  5. 具体如何处理异常,要根据不同的业务需求和异常类型去决定
  6. 尽量添加finally语句块去释放占用的资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值