JVM基础篇-04

举报
kwan的解忧杂货铺 发表于 2024/08/25 00:49:34 2024/08/25
【摘要】 1.异常机制的过程Java 的异常处理机制允许程序在运行时检测和处理错误或异常情况,以提高程序的可靠性和健壮性。以下是 Java 异常处理机制的基本过程:抛出异常(Throwing Exceptions):当在程序执行过程中发生错误或异常情况时,可以使用throw语句手动抛出一个异常对象。异常对象通常是 Exception 类的子类的实例,它包含有关错误情况的详细信息。捕获异常(Catch...

1.异常机制的过程

Java 的异常处理机制允许程序在运行时检测和处理错误或异常情况,以提高程序的可靠性和健壮性。以下是 Java 异常处理机制的基本过程:

  1. 抛出异常(Throwing Exceptions)
    当在程序执行过程中发生错误或异常情况时,可以使用throw语句手动抛出一个异常对象。异常对象通常是 Exception 类的子类的实例,它包含有关错误情况的详细信息。

  2. 捕获异常(Catching Exceptions)
    使用try语句块可以将可能引发异常的代码包围起来。然后可以使用一个或多个catch块来捕获并处理特定类型的异常。每个catch块可以处理一个特定类型的异常,并提供相应的处理逻辑。

  3. 处理异常(Handling Exceptions)
    catch块中,可以编写处理异常的代码,例如记录错误日志、显示错误消息、修复问题等。处理异常的方式可以根据程序的需要而定。

  4. 清理资源(Cleaning Up Resources)
    使用finally块可以确保在无论是否发生异常都会执行特定的代码块,例如释放资源、关闭文件或网络连接等。finally块中的代码将始终执行,即使在try块或catch块中发生了return语句。

以下是一个简单的 Java 异常处理的示例代码:

public class ExceptionExample {
    public static void main(String[] args) {
        try {
            int result = divide(10, 0);
            System.out.println("Result: " + result);
        } catch (ArithmeticException e) {
            System.out.println("Error: " + e.getMessage());
        } finally {
            System.out.println("Cleanup code here");
        }
    }

    public static int divide(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("Cannot divide by zero");
        }
        return a / b;
    }
}

在上面的代码中,divide方法会抛出一个 ArithmeticException 异常,当尝试除以零时。在main方法中,使用try块捕获了这个异常,并在catch块中进行处理,最后在finally块中执行清理操作。

请注意,Java 中的异常处理是一种重要的编程实践,但滥用异常处理可能会导致代码变得复杂难以理解。正确地使用异常处理可以帮助您编写更健壮和可维护的代码。

2.异常体系

Error错误::程序无法处理的严重错误,我们不作处理,这种错误一般来说与操作者无关,并且开发者与应用程序没有能力去解决这一问题,通常情况下,JVM 会做出终止线程的动作.

Exception异常::异常可以分为运行时异常和编译期异常

  • RuntimeException:即运行时异常,我们必须修正代码

    • 这些异常通常是由于一些逻辑错误产生的这类异常在代码编写的时候不会被编译器所检测出来,是可以不需要被捕获,但是程序员也可以根据需要行捕获抛出,(不受检查异常)这类异常通常是可以被程序员避免的。

    • 常见的 RuntimeException 有:NullpointException(空指针异常),ClassCastException(类型转 换异常),IndexOutOfBoundsException(数组越界异常)等。

  • 非 RuntimeException编译期异常,必须处理,否则程序编译无法通过

  • 这类异常在编译时编译器会提示需要捕获,如果不进行捕获则编译错误。

  • 常见编译异常有:IOException(流传输异常),SQLException(数据库操作异常)等。

image-20230815113157598

3.异常输出打印的常用方法

方法方法 说明
public String getMessage() 回关于发生的异常的详细信息。这个消息在 Throwable 类的构造函数中初始化了
public Throwable getCause() 返回一个 Throwable 对象代表异常原因
public String toString() 使用 getMessage()的结果返回类的串级名字
public void printStackTrace() 打印 toString()结果和栈层次到 System.error,即错误输出流

示例:

public class Demo {
    public static void main(String[] args) {
        int a = 520;
        int b = 0;
        int c;
        try {
            System.out.println("这是一个被除数为0的式子");
            c = a / b;
        } catch (ArithmeticException e) {
            System.out.println("除数不能为0");
        }
    }
}

//运行结果
//这是一个被除数为0的式子
//除数不能为0

我们用上面的例子给出异常方法的测试

// System.out.println(e.getMessage()); 结果如下:
/ by zero
// System.out.println(e.getCause()); 结果如下:
null
// System.out.println(e.toString()); 结果如下:
java.lang.ArithmeticException: / by zero
// e.printStackTrace(); 结果如下:
java.lang.ArithmeticException: / by zero
	at cn.bwh_01_Throwable.Demo.main(Demo.java:10)

4.Throw 和 Throws 的区别

Throw

  • 作用在方法内,表示抛出具体异常,由方法体内的语句处理。

  • 具体向外抛出的动作,所以它抛出的是一个异常实体类。若执行了 Throw 一定是抛出了某种异常。

Throws

  • 作用在方法的声明上,表示如果抛出异常,则由该方法的调用者来进行异常处理。

  • 主要的声明这个方法会抛出会抛出某种类型的异常,让它的使用者知道捕获异常的类型。

  • 出现异常是一种可能性,但不一定会发生异常。

5.运行时异常

运行时异常 描述
NullPointerException 试图访问空对象的属性或调用空对象的方法。
ArithmeticException 数学运算中,如除以零时抛出的异常。
ArrayIndexOutOfBoundsException 访问数组不存在的索引位置时抛出的异常。
IllegalArgumentException 参数不符合方法预期要求时抛出的异常。
NumberFormatException 尝试将字符串转换为数字类型,但格式错误。
ClassCastException 尝试强制转换不兼容类型的对象时抛出的异常。
ConcurrentModificationException 多线程环境下,迭代同时修改集合抛出的异常。
UnsupportedOperationException 调用对象上不支持操作时抛出的异常。

上述表格中只是列举了一些常见的运行时异常及其描述。在编写代码时,应该遵循良好的编码实践,以避免这些异常的发生,并且在必要时进行适当的异常处理。

6.非运行时异常

非运行时异常(Non-runtime Exceptions),也称为编译时异常(Checked Exceptions),是 Java 异常体系的另一类重要异常。与运行时异常不同,编译时异常必须在方法签名中显式声明,并且在代码中要求进行异常处理,否则程序将无法通过编译。

以下是一些常见的非运行时异常及其描述:

非运行时异常 描述
IOException 输入输出操作期间可能发生的异常。
FileNotFoundException 尝试打开不存在文件时抛出的异常。
ParseException 解析字符串为日期、时间等格式时可能出错。
SQLException 访问数据库时可能发生的异常。
ClassNotFoundException 尝试加载不存在的类时抛出的异常。
InterruptedException 线程在等待、睡眠等操作中被中断时抛出的异常。
NoSuchMethodException 调用不存在的方法时抛出的异常。
NoSuchFieldException 访问不存在的字段时抛出的异常。

在编写代码时,处理非运行时异常的方法有两种:使用try-catch块捕获异常或使用throws关键字在方法签名中声明异常,并将异常传递给调用者来处理。编译时异常的处理强制开发人员在代码中采取措施来处理潜在的异常情况,以确保程序的稳定性和可靠性。

7.try-with-resources 替代 try-catch-finally

面对必须要关闭的资源,我们总是应该优先使用 try-with-resources 而不是 try-finally。随之产生的代码更简短,更清晰,产生的异常对我们也更有用。try-with-resources 语句让我们更容易编写必须要关闭的资源的代码,若采用 try-finally 则几乎做不到这点。—— Effecitve Java

Java 从 JDK1.7 开始引入了 try-with-resources ,在其中定义的变量只要实现了 AutoCloseable 接口,这样在系统可以自动调用它们的 close 方法,从而替代了 finally 中关闭资源的功能。

使用 try-catch-finally 你可能会这样做

try {
    // 假设这里是一组关于 文件 IO 操作的代码
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (s != null) {
        s.close();
    }
}

但现在你可以这样做

try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("test.txt")))) {
    // 假设这里是操作代码
} catch (IOException e) {
    e.printStackTrace();
}

如果有多个资源需要 close ,只需要在 try 中,通过分号间隔开即可

try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("test.txt")));
     BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("test.txt")))) {
    // 假设这里是操作代码
} catch (IOException e) {
    e.printStackTrace();
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。