您的位置:首页 > 编程语言 > Java开发

Java基础知识每日总结(11)---Java异常、断言和日志

2020-06-15 10:34 281 查看

异常、断言和日志

1.简介
在程序运行期间,用户可能会输入错误格式的数据造成程序的崩溃,这时Java使用一种异常处理的错误捕获机制来处理,这包括抛出异常和捕获异常。在测试期间需要进行大量的检测以验证程序操作的正确性,这时可以使用断言来有选择地启用检测。当程序出现错误时,需要用日志记录下出现的问题以备日后的分析。

2.处理错误
在程序运行时,如果由于出现错误而使得某些操作没有完成,程序应该:返回到一种安全状态,并能够让用户执行一些其他的命令;或允许用户保存所有操作的结果,并以妥善的方式终止程序。
下面是程序运行时可能出现的错误:

  • 用户输入错误
  • 设备错误
  • 物理限制
  • 代码错误

对于方法中的错误传统的做法是返回一个特殊的错误码,还有一种是表示错误情况的常用返回值是null引用。但并不是在任何情况下都能够返回一个错误码。
异常具有自己的语法和特定的继承结构。
在Java语言中,异常对象都是派生于Throwable类的一个实例,但是当Java中内置的异常类不能够满足需求,用户可以创建自己的异常类。Java异常层次结构:

Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误,它是程序无法处理的错误。如虚拟机错误、内存溢出错误、线程死锁等等。Exception层次结构是程序本身可以处理的异常,它有2个分支,其中由程序错误导致的异常属于RuntimeException,而程序本身没有问题,但由于像I/O、SQL等这类问题导致的异常属于其他异常。
派生于RuntimeException的异常有以下几种情况:错误的类型转换、数组访问越界、访问null指针;不是派生于RuntimeException的异常包括:试图在文件尾部后面读取数据、试图打开一个不存在的文件、试图根据给定的字符串查找Class对象,而这个字符串表示的类并不存在。应该通过检查数组下标是否越界来避免ArrayIndexOutOfBoundsException异常,在使用变量之前检测是否为null来杜绝NullPointerException的发生。
注:如果出现RuntimeException异常,那么就一定是你的问题。
Java语言规范将派生于Error类或RuntimeException类的所有异常称为非受查异常,这种异常要么不可控要么就应提前避免,所有其他的异常称为受查异常。
一个方法应该在其首部用throws声明所有可能抛出的异常。以下四种情况应该抛出异常:调用一个抛出受查异常的方法、程序运行过程中发现错误,并且利用throw语句抛出一个受查异常、程序出现错误、Java虚拟机和运行时库出现的内部错误。如果一个方法有可能抛出多个受查异常类型,那么就应该在方法的首部列出所有的异常类,每个异常类之间用逗号隔开。但是,不需要声明Java的内部错误,即从Error继承的错误,同样也不应该声明从RuntimeException继承的非受查异常。
注:如果父类方法没有抛出任何受查异常,子类也不能抛出任何受查异常。
写程序时当遇到任何标准异常类都不能解决时,可以定义自己的异常类,即定义一个派生于Exception的类,或者派生于Exception子类的类,自己定义的异常类应该包含两个构造器,一个是默认的构造器,另一个是可以输出详细描述信息的构造器,例父类Throwable的toString方法会打印这些详细信息。

3.捕获异常
如果在程序运行时发生了某个异常但没有在任何地方进行捕获,那么程序就会终止,并在控制台上打印异常信息,这包含异常的类型和堆栈的内容。对于图形界面程序(applet和应用程序),在捕获异常之后也会打印堆栈的信息,但程序将返回用户界面的处理循环中。throws用来声明将要抛出何种类型的异常,而throw用来抛出产生的异常。当一个方法可能会出现异常,但是它不想或没有能力处理这个异常,这时可以在方法声明处用throws来声明抛出异常。此时,谁调用了此方法谁就处理此异常。
throws后面跟单个或多个异常的类型,异常类型间用逗号来分隔。例,

public void test() throws ArithmeticException,ArrayIndexOutOfBoundsException {
}

throws关键字通常用于方法的声明中,如果是Error、RuntimeException或它们的子类,那么可以不使用throws关键字来声明要抛出的异常。编译仍能顺利通过。但在运行时会被系统抛出。
throw关键字通常用于方法体中,程序在执行到throw语句时,立即终止。它后面的语句都不执行,除非调用者捕获并处理了该异常。
要想捕获异常,必须设置try/catch或try/catch-finally语句块。语句:

try {
代码块
产生异常的代码块
}catch(异常类型 ex ) {
对异常处理的代码块
}finally{
代码块
}

通常如果知道如何处理可能出现的异常就将它捕获,如果不知道如何处理就将它抛出。不允许在子类的throws说明符中出现超过父类方法所列出的异常类范围。finally语句块中的代码块无论是否发生异常代码都会执行,catch块中的return语句并不会阻止finally块的运行。
以下3种特殊情况下,finally块不会被执行:

  • 在finally语句块中发生了异常
  • 在前面的代码中用了System.exit()退出程序
  • 程序所在的线程死亡

Java的异常处理是结构化,不会因为一个异常影响整个程序的执行。例,当try代码块中的语句发生了异常,程序就会调转到catch代码块中执行,执行完catch代码块中的程序代码后,继续执行catch代码块后的其他代码。不会执行try代码块中发生异常语句后面的代码。
在程序中想终止代码的执行可以使用java.lang.System下的exit(int status)方法,它可以终止当前运行的Java虚拟机,方法参数为非0整数。
Java中常见的RuntimeException异常,写异常时可通过try…catch语句捕获:

异常对象常用的3个方法:

  • getMessage()函数:获取异常信息
  • toString()函数:将异常对象转换为字符串,其中包括异常类型与错误信息
  • printStackTrace()函数:指出异常的类型、性质、栈层次及出现在程序中的位置

在一个try语句块中可以捕获多个异常类型,即try块后可接0个或多个catch块,并对不同类型的异常做出不同的处理,即对每个异常类型使用单独的catch语句。如果没有catch块,则必须有一个finally块。
捕获多个异常时,异常变量隐含为final变量。建议在多个catch块语句后加一个catch(Exception)来处理可能会被遗漏的异常。可以在finally语句块中释放被占用的资源。
在try…catch语句中,多个catch的顺序一定要遵循“子类在上,父类在下”的规则。
注:当有多个catch语句时,多个catch语句中的异常类型不能相同。

在使用异常时可以使用Java内置的异常类,也可以通过自定义异常来描述特定业务产生的异常类型。所谓自定义异常就是定义一个继承Throwable或它的子类的类。

在使用异常时常常会遇到这样的问题:A方法会抛出一个异常且它调用了B方法,而B方法也会抛出一个异常,那么此时A方法是抛出一个原有的异常还是抛出一个新的异常?此时就出现了异常链即创建了新的异常但保留了原有异常的信息,将异常发生的原因一个传一个串起来,把下层的异常信息传递给上层,这样逐层抛出。其主要实现形式有两种:

使用异常的一些注意项:

  • 异常处理不能代替简单的测试
  • 不要过分地细化异常
  • 利用异常层次结构
  • 不要压制异常
  • 早抛出,晚捕获

4.断言和日志暂无

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: