Java 异常机制总结


前言

  本文是对《Java核心技术卷Ⅰ》(第十版)第七章异常部分(264-285)的学习总结,目的是记录自己的学习路径,以及方便日后查看、复习、补充。

Java异常机制

  与大多数编程语言一样,Java提供了异常处理(Exception Handing)机制,这种机制能够将程序中可能出现的错误进行捕获并进行对应的处理,以增强程序的健壮性。
在这里插入图片描述

异常层次结构

  在Java 程序设计语言中,异常对象都是派生于Throwable类 的一个实例,所有的异常都是由Throwable类继承而来。Throwable类具有两个子类:Error类Exception类

  Error类 描述了Java运行时系统内部错误资源耗尽错误 。应用程序不应该抛出这种类型的异常对象,我们也无法处理该类异常。Exception类 分为两个分支:RuntimeException类 IOException类 其中,由程序本身错误造成的异常属于RuntimeException异常,而程序本身没有问题,但是由于诸如I/O错误这类问题导致的异常属于其他异常。

  原则上讲,异常处理机制关注的是RuntimeException异常,该类异常往往由程序本身造成,程序员需要对自己所写的bug负责 。

受查异常

  Java语言规范将派生于Error类和RuntimeException类的所有异常称为非受查(unchecked)异常,而其他所有异常称之为受查(checked)异常。这个概念十分重要,简单粗暴的理解,受查异常即需要手动去抛出的异常,一般指由程序外部因素造成的异常(如空文件异常),程序语言本身无法控制外部因素,不确定是否会发生异常,所以要手动去检查异常。

throws语句

声明受查异常

  方法应该在首部声明所有有可能抛出的异常,这样可以从首部反映出这个方法可能抛出哪类受查异常,以便于调用该方法的人做进一步的处理 。Java提供了throws语句声明异常,语法格式如下——

	public FileInputStream(String name) throws FileNotFoundException

  通常遇到以下4种情况应该使用throws抛出异常:
  1. 调用抛出受查异常的方法,如方法中调用了FileInputStream;
  2. 程序运行过程发现错误,并利用throws抛出异常,这种情况常与try-catch结合使用;
  3. 程序本身错误,如数组越界,这种情况不常用,低级错误应当在主观上避免;
  4. Java虚拟机和运行库出现的内部错误,这种情况也不常用,这是难以抗拒的异常。

  抛出异常的使用形式:

class MyAnimation{
	...
	public Image loadImage(String s) throws IOException,FileNotFoundException{
		// code
	} 

  多个异常使用逗号隔开。
  总之,一个方法必须声明所有可能抛出的受查异常,而非受查异常,要么不可控(Error),要么需要在debug层面避免(RuntimeException)特别的,如果在子类中覆盖了超类的一个方法,子类方法中声明的受查异常不能比父类声明的异常更通用。

throws 抛出异常

  throws除了可以在方法首部声明所抛出异常之外,还可以在程序任意位置抛出异常,具体使用方式形如——

	if(触发IO异常判定条件)
		throws new IOException(); 

  一旦抛出异常,throws所在的方法不可能返回到调用者,该方法此刻结束。

捕获异常

try-catch块

  与大多数编程语言一样,Java提供了try-catch捕获异常的方法,语法如下:

	try
	{
		//code
	}
	catch(Exception e)
	{
		// handle exception
	}

  如果在try语句块中没有抛出异常,try语句块全部代码将会执行,catch语句块不执行
  如果在try语句块中出现异常,并被对应的catch语句中的异常类型匹配,那么该异常将被捕获:try语句块中抛出异常后的代码不被执行,捕获异常的catch语句块执行
  如果出现异常,且不与任何catch说明的异常匹配,那么该方法立刻退出

  多个catch语句块可以合并,但此时异常变量e隐含为final。

	try
	{
		//code
	}
	catch(FileNotFoundException|IOException e)
	{
		// handle exception
	}

  上文中提到过,子类覆盖父类方法,不能使用throws抛出更特化的异常,但是如果父类方法没有声明任何异常,而子类的方法中存在异常,此时throws语句无法使用,则可以使用try-catch去捕获异常。实际上,throws与try-catch组合使用效果更佳,try-catch捕获异常作为异常原因,然后在catch语句中使用throws抛出新的异常,来进一步解释该异常形成的原因,比如:

	try
	{
		
		// access database
	}
	catch(SQLException e)
	{
		Throwable se = new ServletException("database error");
		se.initCause(e);
		throw se;
	}

  此时,抛出的se异常对象具有更详细的信息和异常类型。

finally语句

  try-catch在捕获异常之后,通常会跳过一些代码块,甚至直接退出方法,这个时候,就需要finally语句来做一些“善后工作”。Java提供了finally语句,无论是否有异常发生,该语句都会被执行:

	try{
		//1
		//code that might throw exceptions
		//2
	}
	catch(Exception e)
	{
		//3
		//handle exception
		//4
	}
	finally
	{
		//5
	}
	//6

  如果代码没有异常,先执行try语句块,然后执行finally,执行顺序:1->2->5->6
  如果异常被catch捕获,先执行try语句块异常之前的代码,然后catch,最后finally,执行顺序:1->3->4->5->6
  如果异常被catch捕获,且catch抛出新的异常,那么执行顺序变成:1->3->5
  如果出现catch无法捕获的异常,那么先执行try异常之前的代码,catch块跳过,finally块执行,然后方法退出,执行顺序变成:1->5
  特别的,如果finally有return语句,那么会覆盖之前方法中所有的return语句

带资源的try语句

  try抛出异常后,很多代码块会被跳过,导致一些资源没有及时回收。finally机制提供了一个回收资源的机会,但是同时也带来一个问题,如果finally语句块中也抛出异常,那么会覆盖try语句中的异常,那么我们原本真正想要处理的异常就无法正确的返回到调用者了。因此,Java7 提供了try资源处理机制,可以把资源回收的问题交给try,语法格式如下:

	try(Scanner in = new Scanner(System.in))
	{
		// exception
	}

  当try正常退出时,in打开的输入流会自动关闭。

分析堆栈轨迹元素

  堆栈轨迹(Stack trace)是一个方法调用过程的列表,包含了程序执行过程中的方法调用信息,如类名、方法名和所在代码段行号等。可以通过Throwable类的printStackTrace方法访问堆栈轨迹文本描述信息,也可以通过getStackTrace方法获取StackTraceElement对象数组,获取文件名、行号和类名、方法名等信息,演示程序如下:

import java.util.Scanner;

public class StackTrace {
    public static int factorial(int n){
        System.out.println("factorial("+n+"):");
        Throwable t = new Throwable();
        StackTraceElement[] stackTraceElements = t.getStackTrace();
        for(StackTraceElement elem:stackTraceElements){
            System.out.println(elem);
        }

        int r;
        if(n<=1) r=1;
        else r = n*factorial(n-1);
        System.out.println("return "+r);
        return r;
    }

    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        factorial(in.nextInt());
    }
}

在这里插入图片描述
  有些时候编译器不提供这些信息的时候,可以手动输出,有助于debug。

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值