【Java SE学习】—— java中的异常处理

分类

Java把所有的非正常情况分成两种:异常和错误,他们都继承Throwable父类

示例方法

  • String getMessage():返回该异常的描述信息(提示给用户)
  • String toString():返回该异常的类型和描述信息(不用)
  • void printStackTrace():打印异常的跟踪栈信息到控制台,包括异常的类型、异常的原因、异常出现的位置(开发和调试)

异常体系

  1. 编译时异常(有错编译器就过不了)
  2. 运行时异常

使用try…catch捕获异常

程序运行出现异常,系统会自动生成一个异常对象,该异常对象被提交给java运行时环境,这个过程被称为抛出异常

  • 如果执行 try 块里的代码时出现异常,Java 运行时环境收到异常对象后,会寻找能处理该异常对象的 catch 块,如果找到合适的 catch 块,则把该异常对象交给该 catch 块处理,这个过程被称为捕获(catch)异常
  • 如果 Java 运行时环境找不到捕获该异常的 catch 块,则使用全局默认的DefaultUncaughtExceptionHandler(处理方式是 e.printStackTrace(System.err)),然后运行时环境终止,该线程也将退出
  • 在处理多种异常类型时,必须先捕获子类类型异常,后捕获父类类型异常,否则编译报错(最后捕获 Exception 类型异常,确保异常对象能被捕获到)
  • 不管 try 块中的代码是否出现异常,也不管哪一个 catch 块被执行,甚至在 try 块或 catch 块中执行了 return 语句,finally 块总会被执行(除非在 try 块或会执行的 catch 块中调用退出 JVM 的相关方法)
  • try 块必须和 catch 块或和 finally 块同在,不能单独存在,catch 块或和 finally 块二者必须出现一个,finally 块必须位于所有的 catch 块之后
  • 当程序执行 try 块、catch 块时遇到 return 或 throw 语句时,系统不会立即结束该方法,而是去寻找该异常处理流程中是否包含 finally 块,如果有 finally 块,系统立即开始执行 finally 块——只有当 finally 块执行完成后,系统才会再次跳回来执行 try 块、catch 块里的 return 或 throw 语句;如果 finally 块里也使用了 return 或 throw 等导致方法终止的语句,finally 块已经终止了方法,系统将不会跳回去执行 try 块、catch 块里的任何代码

使用throws声明抛出异常

语法格式

[修饰符] 返回值类型 方法名(参数列表) throws 异常类A, 异常类B, ...{}
  1. 在可能出现异常的方法上声明可能抛出的异常类型,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常
  2. 当前方法使用throws声明抛出异常,该异常将交给上一级调用者处理,调用者要么try…catch,要么也throws
  3. 如果最上级的main方法也抛出异常,该异常将交给JVM处理
  4. 子类方法声明抛出的异常类和父类方法声明抛出的异常类相同或者是其子类(运行时异常除外)

使用throw自行抛出异常

理解“自行抛出异常”:原来的异常是出现异常后,系统生成异常对象交给JAVA运行环境。现在改成自己生成异常对象交给java。

语句格式

throw new 异常类(异常信息);//终止方法

Java中的throw语句用于抛出一个异常。当程序遇到某种错误情况时,可以使用throw语句将异常传递给调用者。调用者可以选择捕获并处理这个异常,或者继续向上抛出。

throw语句的基本语法如下:

    throw 异常对象;

其中,异常对象可以是Java预定义的异常类(如NullPointerException、ArrayIndexOutOfBoundsException等),也可以是自定义的异常类。

下面是一个简单的示例,演示了如何使用throw语句抛出异常:

 public class ThrowDemo {
    public static void main(String[] args) {
        try {
            int age = -1;
            if (age < 0) {
                throw new IllegalArgumentException("年龄不能为负数");
            } else {
                System.out.println("年龄为:" + age);
            }
        } catch (IllegalArgumentException e) {
            System.out.println("捕获到异常:" + e.getMessage());
        }
    }
}

    

在这个示例中,我们定义了一个名为ThrowDemo的类,其中包含一个main方法。在main方法中,我们使用try-catch语句来捕获可能抛出的异常。首先,我们定义了一个整数变量age,并将其值设置为-1。然后,我们使用if语句判断age是否小于0。如果小于0,我们使用throw语句抛出一个IllegalArgumentException异常,并附带一条错误信息。如果age大于等于0,我们打印出年龄的值。在catch语句中,我们捕获到异常后,打印出异常的错误信息。

自定义异常类型

自定义Runtime异常,应继承RuntimeException(常用)

自定义 Checked 异常,应继承 Exception

// 自定义业务逻辑异常
public class LogicException extends RuntimeException {
    // 无参数的构造器
    public LogicException() {
        super();
        //super表示当前对象的父对象,此处为子类的构造方法中调用父类的指定构造器 `super(name, age);`
    }
    // 带一个字符串参数的构造器
    public LogicException(String message) {
        super(message);
    }
    // message 当前异常的原因/信息;cause 当前异常的根本原因
    public LogicException(String message, Throwable cause) {
        super(message, cause);
    }
}

异常转移和异常链

异常转移

异常转移,本质上是将一种异常转换为另一种新的异常。这种转换过程可能使异常信息更加明确和准确,从而更好地表达程序发生异常的原因。

:程序线捕获原始异常,然后抛出一个新的业务异常,新的业务异常中包含了对用户的提示信息。

异常转移的例子:

假设我们有一个方法,该方法需要接收一个整数参数,并返回这个整数的平方。但是,如果传入的整数是负数,那么这个方法就会抛出一个IllegalArgumentException异常。我们可以使用异常转移来将这个异常转换为更具体的异常类型。

public int square(int number) {
    if (number < 0) {
        throw new NegativeNumberException("Negative numbers are not allowed");
    }
    return number * number;
}

    

在这个例子中,如果传入的整数是负数,我们就抛出了一个NegativeNumberException异常。这样,调用者就可以知道是因为传入了负数而导致的异常,而不是因为其他原因。

异常链

:一个异常的发生是由于另一个异常引起

在Java中,异常链是指一个异常被另一个异常所抑制。当一个异常被抑制时,它会被添加到抑制异常列表中,并且可以通过调用getSuppressed()方法来获取这个列表。

下面是一个Java中的异常链的例子:

public class ExceptionChainExample {
    public static void main(String[] args) {
        try {
            method1();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void method1() throws Exception {
        try {
            method2();
        } catch (Exception e) {
            throw new Exception("Exception in method1", e);
        }
    }

    private static void method2() throws Exception {
        try {
            method3();
        } catch (Exception e) {
            throw new Exception("Exception in method2", e);
        }
    }

    private static void method3() throws Exception {
        throw new Exception("Exception in method3");
    }
}

    

在这个例子中,method3抛出了一个异常,然后method2捕获了这个异常并将其作为原因抛出了一个新的异常。接着,method1捕获了这个新的异常并将其作为原因抛出了另一个新的异常。最后,main方法捕获了这个最终的异常并打印了异常链。

  • 23
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值