Java异常处理 探险

Java异常机制使异常处理代码和正常业务代码分离,让程序有更好的容错性、更加健壮。目前主流编程语言如C++、C#、Ruby、Python等都提供了异常处理机制。

Javc异常主要依赖于try、catch、finally、throw、throws五个关键字,Java7进一步增强了异常处理机制的功能,包括带资源的try语句,捕获多异常的catch两个新功能(简化了异常处理)。


Java将异常分为两种:Checked异常和Runtime异常

Java异常处理 探险_第1张图片

Java常见异常思维导图整理如下:

Java异常处理 探险_第2张图片

我们先来看看异常处理语法结构:

try {
	// 业务流程
	...
} catch(Exception e) {
	// 异常处理块
	...
} finally {
	//资源回收块
	...
}

1.使用try...catch捕获异常


1)当执行try的业务逻辑代码出现异常,系统自动生成一个异常对象并提交给Java运行时环境,即抛出异常(throw)。

2)当Java运行时环境收到异常对象时,会寻找处理该异常的catch块(依次判断该异常对象是否是catch块后异常类或者其子类的实例),找到则交付处理,即捕获异常(catch),如果找不到对应的catch块,Java运行时环境终止,程序在此退出。



2.访问异常信息


所有的异常对象都包含如下几个常用方法:

getMessage():返回该异常的详细描述字符串

printStackTrace():将该异常的跟踪栈信息输出到标准输出流

printStackTrace(PrintStream s):将该异常的跟踪栈信息输出到指定输出流

getStackTrace():返回该异常的跟踪栈信息

示例:

try {
	...
} catch(NullPointerException e) {
	System.out.println(e.getMessage()); // 返回该异常的详细描述字符串
	e.printStackTrace(); // 将该异常的跟踪栈信息输出到标准输出流
}



3.使用throws声明抛出异常


当前方法不知如何处理出现的异常,抛由上一级调用者处理;如果main方法也要抛出异常,则交由JVM处理(打印异常的跟踪栈信息并中止程序运行)

public class ThrowsDemo{
	// 此处异常将交由JVM处理
	public static void main(String[] args) throws IOException{
		...
	}
}
注意:子类方法抛出的异常范围应小于等于父类



4.使用throw抛出异常


自行抛出异常,throw抛出的是一个异常实例,每次只能抛出一个

throw抛出Checked异常:throw语句要放在try块里或者一个带throws声明抛出的方法中

throw抛出Runtime异常:自由放

try (
	if(...){
		throw new RuntimeException("我是一个throw抛出的异常..");
	}
	...
} catch(Exception e) {
	...
} finally {
	...
}



5.自定义异常类


继承Exception 或者 RuntimeException(Runtime异常),提供两个构造方法:无参和带一个字符串(异常对象的描述信息,getMessage()的返回值)参数的构造方法

public class MyException extends RuntimeException{
	// 无参构造方法
	public MyException(){}
	// 带一个参数的构造方法
	public MyException(String msg){
		super(msg); // 
	}
}



6.catch和throw同时使用


多个方法协作处理同一个异常,可在catch块中结合throw语句完成,在大型企业级应用中常见,企业级应用对异常处理通常分为两部分:(1)后台通过日志记录异常详情;(2)应用向应用使用者传达提示。

public class ExceptionTest{
	
	public void init(String msg) throws MyException{
		try (
			...
		} catch(Exception e) {
			e.printStackTrace();
			// 再次抛出异常
			throw new MyException("必须是数字..");
			...
		} 
		if(...){
			throw new MyException("数字必须大于5位..");
		}

	}
	
	public static void main(String[] args){
		ExceptionTest et = new ExceptionTest();
		try (
			...
		} catch(MyException e) {
			// 再次捕获到异常并处理
			System.err.println(e.getMessage());
		} 
	}
}

7.异常链


分层结构:表现层(用户界面)-->中间层(业务逻辑)-->持久层(保存数据)

上层功能的实现严格依赖于下层的API,不会跨层访问

异常转译:捕获异常后抛出一个新的业务异常(包含对用户的提示信息)

这种把捕获的一个异常接着抛给另一个异常,并把原始异常信息保存下来是一种典型的链式处理(23种设计模式之一:职责链模式),也被称为“异常链”。


8.异常跟踪栈


当产生异常的时候,异常从方法1触发,传到方法2,再传到方法3...最后传到main方法,在main方法终止,这个过程就是Java的异常跟踪栈。

方法调用栈:面向对象的应用运行时,会发生一系列方法调用,从而形成“方法调用栈”。



9.Java7增强的功能


1)Java7提供了多异常捕获

try {
	...
} catch(IndexOutOfBoundsException|NumberFormatException|NullPointerException e) {
	e.printStackTrace();
}


2)Java7增强了try语句的功能

允许在try关键字后加 ( ) ,圆括号可声明、初始化一个或多个资源(指那些必须在程序结束时显式关闭的资源,比如数据库连接、网络连接、流等,这些资源实现类必须实现AutoCloseable或Closeable,实现close()方法),try语句在该语句结束的时候自动关闭这些资源。

自动关闭资源的try语句相当于包含了隐式的finally块(用于关闭资源),故这个try语句可以既没有catch块,也没有finally块。

try (
	// 声明、初始化可关闭资源,try语句会自动关闭
	BufferedReader br = new BufferedReader(new FileReader("Test.java"));){
	// 使用资源
	System.out.println(br.readLine());
	...
} catch(Exception e) {
	...
} finally {
	...
}


10.Java异常处理使用建议


1)不要过度使用异常
2)try块避免庞大
3)避免使用CatchAll语句(一种异常捕获模块),CatchAll语句如下:
try (
	...
} catch(Throwable t) {
	t.printStackTrace();
}
4)不要忽略捕获到的异常



11.补充

1)try后的 { } 不可以省略

2)父类异常的catch块都应该排在子类异常catch块的后面

3)异常处理结构try块是必需的,catch块和finally块至少出现其中一个
4)return方法

try {
	...
} catch(Exception e) {
	return; // 强制方法返回
	// System.exit(1); // 退出虚拟机,finally块失去执行的机会
} finally {
	...
}
5)尽量避免finally块中使用return或throw等导致方法终止的语句

try {
	...
	return true; // 失效,这里不会终止方法,接下来还会执行finally块,
				 // 除非调用System.exit(1);退出虚拟机,finally块将失去执行的机会
} catch(Exception e) {
	...
} finally {
	...
	return false; // 返回false
}


你可能感兴趣的:(java,异常处理)