Java 核心技术卷1 --第七章 异常、断言和日志

Github代码链接: https://github.com/deyou123/corejava.git

第七章 异常、断言和日志

由于程序的错误或一些外部环境的影响造成用户数据的丢失,为了避免:

  • 向用户通告错误;
  • 保存所有的工作结果;
  • 允许用户以妥善的形式退出程序;

异常处理 :可能造成程序崩溃的错误输入。

7.1 处理错误

如果由于出现错误二十的某些操作没有完成,程序应该:

  • 返回到一种安全状态,并能够让用户执行一些其他的命令;
  • 允许用户保存所有操作的结果,并以妥善的方式终止程序。

这并不容易:检测错误条件的代码通常离那些能让数据恢复到安全状态,或者能够保存用户的操作结果,并正常的退出程序的代码很远。
异常处理的任务就是将控制权从错误产生的地方转移给能处理这种情况的错误处理器。

1、用户输入错误 (URL)
2、设备错误(打印机)
3、物理限制(磁盘满了)
4、代码错误
程序方法有可能无法正确执行。

7.1.1 异常分类

异常对象都是派生于Throwable类的一个实例。
Java 核心技术卷1 --第七章 异常、断言和日志_第1张图片

  • Error:描述了Java运行时系统的内部错误和资源耗尽错误。

    • 应用程序不应该抛出这种类型的对象。
    • 如果出现了这样的内部错误,除了通告给用户,并尽力使程序安全的终止之外,在也无能为力了。
  • Exception:

    • RuntimeException:由程序错误导致的异常
      • 错误的类型转换
      • 数组访问越界
      • 访问null指针
    • 其他异常:程序本身没有问题,由像IO错误这类问题导致的异常属于其他异常。
      • 试图在文件尾部后面读取数据
      • 试图打开一个不存在的文件
      • 试图根据给定的字符串查找Class对象,而这个字符串表示的类并不存在。

如果使RuntimeException异常,那么一定是你的问题。
处理不存在的文件;可能在检查他是否存在之前就已经被删除了;因此“是否存在”却决于环境,而不是只是取决于你的代码;

非受查异常: 派生于Error或RuntimeException类的所有异常。
受查异常: 所有的其他异常。

  • 编译器将核查是否为所有的受查异常提供了异常处理器。

7.1.2声明受查异常

  • 如果遇到无法处理的情况,那么java的方法可以抛出一个异常。

  • 一个方法不仅需要告诉编译器将要返回什么值,还要告诉编译器有可能发生什么错误。

  • 读取文件的代码可能读取的文件不存在,或内容为空;就会可能抛出IOException;

  • 方法应该在其首部生命所有可能抛出的异常;从首部反映出这个方法可能抛出哪类受查异常。

  • 在自己编写方法时,不必将所有可能抛出的异常都进行声明;

以下情况应该抛出异常:
1) 调用一个抛出受查异常的方法:FileInputStream构造器。
2)程序运行过程中发现错误,并且利用throw语句抛出一个受查异常
3)程序出现错误: a[-1]:Array’Index’OutofBoundsException
4)Java虚拟机和运行时库出现的内部错误。

  • 1和2 必须告诉调用这个方法的程序员有可能抛出异常。
  • 其他可能被他人使用的java方法,在方法首部生命这个方法可能抛出的异常。
  • 如果有多个受查异常类型,用逗号隔开;
  • 不需要声明java的内部错误,即从Error继承的错误;任何程序代码都具有抛出那些异常的潜能,并且我们对其没有任何控制能力。
  • 同样,也不应该声明从RuntimeException继承的那些非受查异常;这些运行时错误完全在我们的控制之下;ex:数组下标,应该将更多的时间花费在修正程序中的错误上,而不是说明这些错误发生的可能性上。
  • 总之,一个方法必须声明所有可能抛出的受查异常;而非受查异常要么不可控制(Error),要么就应该避免发生(RuntimeException);
警告
  • 如果在子类覆盖了一个超类的方法,子类方法中声明的受查异常不能比超类方法中生命的异常更通用:也就是说,子类方法中可以抛出更特定的异常(特殊化而不是通用化),或是根本不抛出任何一场。
  • 如果超类没有抛出任何受查异常,子类也不能抛出任何受查异常。

7.1.3 如何抛出异常

EOFException(String msg):在输入过程中,遇到一个未预期的EOF后的信号;

对于一个已存在的异常类,将其抛出非常容易:
1、找到一个合适的异常类
2、创建这个类的一个对象
3、将对象抛出
一旦方法抛出了异常,这个方法就不可能返回到调用者;不必为返回的默认值或错误代码担忧。

7.1.4 创建异常类

  • 需要定义一个派生于Exception或派生于Exception子类(RuntimeException等)的类。
  • 应该包含两个构造器,一个默认构造器;一个带有描述详细信息的构造器;

7.2 捕获错误

7.2.1 捕获异常

  • 如果某个异常发生时没有在任何地方进行捕获,那程序就会终止执行,并在控制台上打印出异常信息;其中包括异常的类型和堆栈的内容。
  • 对于图形界面程序,在捕获异常后,也会打印出堆栈的信息,但程序将返回到用户界面的处理循环中(调试GUI程序时,最好保证控制台窗口可见,并且没有被最小化)

捕获异常,必须设置try-catch语句块。

  • 如果try语句块中任何代码抛出了一个在catich子句中说明的异常类:

    • 程序将跳过try语句块的其余代码
    • 程序将执行catich子句中处理器代码
  • 如果try语句中的代码没有抛出异常,那么程序将跳过catich子句。

  • 如果方法中的任何代码抛出了一个在catch子句中没有生命的异常类型,那么这个方法会立刻退出。

  • 通常,最好选择什么也不做,而是将异常传递给调用者;这样方法可能抛出一个异常。

  • throws,如果调用了一个抛出受查异常的方法,就必须对他处理,或者继续传递。

  • 通常,应该捕获那些知道如何处理的异常,而将那些不知道处理的异常继续进行传递。

  • 如果像传递一个异常,就必修在方法的首部添加一个throws说明符,一边告知调用者这个方法可能抛出异常。

  • 例外:如果编写一个没有抛出异常的, 覆盖父类的方法,那么这个方法就必须捕获方法代码中出现的每一个受查异常;不允许子类的throws说明符中出现超过父类方法所列出的异常类范围。

7.2.2 捕获多个异常

  • 每个异常类型使用一个单独的catch子句。
  • 假设缺少文件和未知主机异常的动作是一样的,就可以合并catch子句(并且异常类型彼此之间不存在子类关系):
catch(FileNotFoundException | UnknownHostException e){
   
	

你可能感兴趣的:(Java核心技术第10版,卷1,java)