Java:详解Java中的异常(Error与Exception)

在这篇Java异常教程中,我们会学到Java中的异常(Exception)是什么、checked异常和unchecked的区别是什么,并且还会学到关于Java中处理checked异常的一些很好的实践。

1. Java中的异常(Exception)是什么?

异常就是在程序执行期间发生的打断指令正常执行流程的一个不期望出现的事件。

在Java中,所有的错误和异常都继承自Throwable类。当一个方法内发生错误时,方法会创建一个对象(该对象是Throwable的子类),并把它传递给运行时系统。这个对象就被就做异常对象。

异常对象包含着错误的详细信息,包括错误的类型和该错误发生时系统的状态。创建一个异常对象并把它传递给运行时系统就叫做抛出了一个异常(throwing an exception)。

1.1 异常处理

当我们的应用创建出一个异常对象时,我们有两种方法来处理。

  • 要么我们在方法内处理这个异常;
  • 要么我们把它传给调用方方法,让调用方方法来处理它。

设置一个方法的职责是一个重要的决定。一个方法应该清晰的表明哪些异常场景它会处理,哪些它不会处理。这是在方法语法中使用throw子句来定义的。

为了处理异常,我们必须在try-catch代码块的catch块中捕获该异常。

如果一个应用的异常没有处理,这个异常会传递给Java虚拟机(JVM),JVM通常会停止这个应用。

2. Java中的Checked异常和unchecked异常的区别

2.1 异常层次结构

在Java中,异常明确的分为两种:checked异常和unchecked异常。

2.2 checked异常

Java强制要求在你的应用程序代码中以规范的方式处理这些异常场景。你可以明确的忽略这些异常,把它们传给JVM去处理,但这样是一个坏习惯。规范而言,你必须在你的应用程序中以适当的级别(例如INFO、WARNING等)来处理这些异常,从而你可以告知用户发生了错误并让他稍后重试。

一般而言,checked异常指的都是不受程序直接控制的错误。它们通常都是由于与外部资源/网络交互而发生的,例如数据库问题、网络连接错误、文件丢失等问题。

checked异常是Exception类的子类。

checked异常的例子如:ClassNotFoundException,IOException,SQLException等。

Checked异常例子

Java中的FileNotFoundException是一个checked异常。任何时候,我们想要从文件系统读取一个文件时,Java强制我们处理文件不存在的错误情况。

public static void main(String[] args) 
{
    FileReader file = new FileReader("somefile.txt");
}

在上面的例子中,编译是无法通过的,你会获取到一个编译时异常信息——Unhandled exception type FileNotFoundException(未处理的异常,类型为FileNotFoundException)。

为了使程序能够编译通过,你必须用try-catch代码块来处理这个异常情况。下面给出的代码就完全可以正常编译。

public static void main(String[] args) 
{
    try
    {
        FileReader file = new FileReader("somefile.txt");
    } 
    catch (FileNotFoundException e) 
    {
        //Alternate logic
        e.printStackTrace();
    }
}

2.3 unchecked异常

Java也提供了UncheckedExceptions(不受检查的异常),编译器是不会检查这种异常的。一旦执行力任何有bug的代码就会出现这种异常。

编译器不会强制要求方法声明由unchecked异常的实现抛出的异常。通常,这样的方法也都不会去声明这种异常的。

Unchecked异常是RuntimeException的子类。unchecked异常的例子如:NullPointerException,AritheticException,ArrayStoreException,ClassCastException等。

unchecked异常例子

看下面给出的代码,这段代码编译时没有错误。但是,当你运行这个例子,会抛出一个NullPointerException,NullPointerException是Java中的一个unchecked异常。

public static void main(String[] args) 
{
    try
    {
        FileReader file = new FileReader("pom.xml");
         
        file = null;
         
        file.read();
    } 
    catch (IOException e) 
    {
        //Alternate logic
        e.printStackTrace();
    }
}

记住,checked异常和unchecked异常的最大区别就是:checked异常会被编译器强制检查,以便指出不受系统控制的意外情况(例如:I/O错误)。unchecked异常是在运行时发生的,用于表示编码错误(例如:一个空指针)。

2.4 Error

Error是Throwable的一个子类,它表示一个合理的应用程序不应该尝试捕获并处理的严重问题。大多数此类错误都是异常情况。线程死亡(ThreadDeath)错误虽然是正常情况,但它也是Error的子类,因为绝大部分应用都不应该处理这个错误。

方法不需要在其throws子句中声明任何可能在方法执行期间抛出但未捕获的错误的子类,因为这些错误是任何时候都不应该出现的。

也就是说,出于在编译时检查异常的目的,Error和它的子类都被视为unchecked异常。

为什么Error不用处理呢?因为这类问题在程序中是没有办法处理的。举个例子,像内存溢出(OutOfMemoryError)错误,即使我们捕获到了,也不能处理,你可能会说,那我手动进行一次垃圾收集不可以吗?答案是:不可以!因为内存溢出也就是内存不够用了,JVM是在进行垃圾收集后发现内存不够用才报这个错误的,所以这类问题程序是没办法处理的,而这些问题是可以通过编写高质量的代码来避免的。

3. 处理Java异常的最佳实践

1. 当一个方法不能执行它所代表的功能时,可以使用checked异常。例如,一个叫做prepareSystem()的方法,它通过加载配置文件并使用这些文件来做一些配置,就可以声明抛出一个FileNotFoundException异常,表示这个方法使用文件系统中的配置文件。

2. checked异常理想上不应该用于程序异常,但绝对应该用于资源错误和这中情况下的流程控制。

3. 仅仅抛出方法内怎么也处理不了的异常。方法应该首先尝试在遇到异常时就处理它,当在方法内不可能处理时,再抛出这个异常。

4. 定义一个异常签名的最好方法时把它声明的和方法名相近。如果你的方法是openFile,那么它抛出的异常就可以是FileNotFoundException,如果你的方法名是findProvider,那么它抛出的异常就可以是NoSuchProviderException。

5. 规则就是:如果一个客户端可以合理的从一个异常中恢复为正常,就把这个异常定义为checked异常。如果一个客户端不能从异常中恢复,就把它定义为unchecked异常。

实际上,许多应用程序必须从许多异常中恢复,例如:NullPointerException、IllegalArgumentException等。失败的动作或事务会被中止,但应用必须正常运行并准备为下一个动作或事务服务。

通常,唯一合法的关闭一个应用的时间是在它启动期间。例如,如果一个应用由于配置文件的丢失而不能处理任何业务,那么关闭这个应用就是合法的。

4. 总结

在这篇文章中,我们学习了Java中checked异常和unchecked异常的区别,也学习了如何处理unchecked异常、并从一些例子中学习了Java中异常的层次结构。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值