Java学习概论第十七节

Java异常

一、异常概述

• 这种在运行时出现的意外错误称为“异常”
• 对异常的处理机制也成为判断一种语言是否成熟的标准。
• 好的异常处理机制会使程序员更容易写出健壮的代码,防止代码中Bug的蔓

1、 异常类

Java中的异常类可以分为两种:
• 错误(Error):一般指与虚拟机相关的问题,如系统崩溃、虚拟机错误、
动态链接失败等,这些错误无法恢复或捕获,将导致应用程序中断;
• 异常(Exception):因程序编码错误或外在因素导致的问题,这些问题能
够被系统捕获并进行处理,从而避免应用程序非正常中断,例如:除以0、
对负数开平方根、空指针访问等。

Throwable是所有异常类的父类,Error和Exception都继承此类:
当程序产生Error时,因系统无法捕获Error并处理,程序员将无能为力,
程序只能中断;
当发生Exception时,系统可以捕获并做出处理,因此本章所介绍的异常处
理操作都是针对Exception及其子类而言的。
Exception异常从编程角度又可以分为以下两种类型:
非检查型异常:编译器不要求强制处置的异常,该异常是因编码或设计不当导致的,这种异常可以避免,RuntimeException及其所有子类都属于非检查型异常。
检查型异常:编译器要求及其子类(RuntimeException及其子类除外)都属于检查型异常必须处理的异常,该异常是程序运行时因外界因素而导致的,Exception。

2、常用的异常类

非检查型异常:
类名 说明
ArrayIndexOutOfBoundsException 数组下标越界异常
NullPointerException 空指针访问异常
NumberFormatException 数字格式化异常
ArithmeticException 算术异常,如除以0溢出
ClassCastException 类型转换不匹配异常
检查型异常:
SQLException 数据库访问异常
IOException 文件操作异常
FileNotFoundException 文件不存在异常
ClassNotFoundException 类没找到异常
• 检查型异常体现了Java语言的严谨性,程序员必须对该类型的异常进行处理,否则程序编译不通过,无法运行。RuntimeException及其子类都是Exception的子类,Exception是所有能够处理的异常的父类。
• 异常是在程序执行期间产生的,会中断正常的指令流,使程序不能正常执行下去 。
• 为了使程序出现异常时也能正常运行下去,需要对异常进行相关的处理操
作,这种操作称之为“异常处理”。
• Java的异常处理机制可以让程序具有良好的容错性,当程序运行过程中出
现意外情况发生时,系统会自动生成一个异常对象来通知程序,程序再根据
异常对象的类型进行相应的处理。

Java提供的异常处理机制有两种:
• 使用try…catch捕获异常:将可能产生异常的代码放在try语句中进行隔离,如果遇到异常,程序会停止执行try块的代码,跳到catch块中进行处理。
• 使用throws声明抛出异常:当前方法不知道如何处理所出现的异常,该异
常应由上一级调用者进行处理,可在定义该方法时使用throws声明抛出异常。

3、捕获异常

Java中捕获异常并处理的语句有以下几种:
• try…catch语句
• try…catch…finally语句
• 自动关闭资源的try语句
• 嵌套的try…catch语句
• 多异常捕获
try…catch语句:
(1) 单catch处理语句
• 单catch处理语句只有一个catch,是最简单的捕获异常处理语句:

try { 
	// 产生除以0的算术异常 
	int i = 10 / 0; 
	System.out.println("i的值为:" + i); 
} catch (Exception e) { 
	// 输出异常信息 
	e.printStackTrace(); 
} 
// 该条语句继续执行 
System.out.println("end");

• 所有异常对象都包含以下几个常用方法用于访问异常信息:
• getMessage()方法:返回该异常的详细描述字符串;
• printStackTrace()方法:将该异常的跟踪栈信息输出到标准错误输出;
• printStackTrace(PrintStream s)方法:将该异常的跟踪栈信息输出到指
定输出流;
• getStackTrace()方法:返回该异常的跟踪栈信息。
(2)多catch处理语句

代码1:
Scanner scanner = new Scanner(System.in);  
int array[] = new int[3]; 
try { 
	System.out.println("请输入第1个数:"); 
	String str = scanner.next(); // 从键盘获取一个字符串 
	// 将不是整数数字的字符串转换成整数,会引发NumberFormatException 
 	int n1 = Integer.parseInt(str); 
 	System.out.println("请输入第2个数:"); 
 	int n2 = scanner.nextInt(); // 从键盘获取一个整数 
 	// 两个数相除,如果n2是0,会引发ArithmeticException 
 	array[1] = n1 / n2; 
 	// 给a[3]赋值,数组下标越界,引发ArrayIndexOutOfBoundsException
 	array[3] = n1 * n2; 
 	System.out.println("两个数的和是" + (n1 + n2)); 
 }

代码2catch (NumberFormatException ex) { 
	System.out.println("数字格式化异常!"); 
} catch (ArithmeticException ex) {
	System.out.println("算术异常!"); 
} catch (ArrayIndexOutOfBoundsException ex) { 
	System.out.println("下标越界异常!"); 
} catch (Exception ex) { 
	System.out.println("其他未知异常!"); 
}	
	System.out.println("程序结束!");

try…catch…finally语句:
• 在Java异常处理机制中,提供了finally块,可以将回收代码放入此块中,
不管try块中的代码是否出现异常,也不管哪一个catch块被执行,甚至在try块或catch块中执行了return语句,finally块都会被执行。
• Java垃圾回收机制不会回收任何物理资源,垃圾回收机制只能回收堆内存中对象所占用的内存。在Java程序中,通常使用finally回收物理资源。

FileInputStream fis = null; 
try {  
	// 创建一个文件输入流,读指定的文件 
	fis = new FileInputStream("zkl.txt"); 
} catch (IOException ioe) { 
	System.out.println(ioe.getMessage()); 
	// return语句强制方法返回 
	return; //(1)
	// 使用exit来退出应用 
	// System.exit(0); // (2)
}
finally { 
	// 关闭磁盘文件,回收资源 
	if (fis != null) { 
		try { 
			fis.close(); 
		} catch (IOException ioe) { 
			ioe.printStackTrace(); 
		} 	
	} 
	System.out.println("执行finally块里的资源 • 回收!");
}

自动关闭资源的try语句:
• 从Java 7开始,增强了try语句的功能,允许在try关键字后紧跟一对小括
号,在小括号中可以声明、初始化一个或多个资源,当try语句执行结束时会自动关闭这些资源。

public static void main(String[] args) { 
	// 自动关闭资源的try语句,JDK 7.0以上才支持 
	try (FileInputStream fis = new FileInputStream("zkl.txt")) {
		// 对文件的操作... 
	} catch (IOException ioe){
		System.out.println(ioe.getMessage()); 
	} 
	// 包含了隐式的finally块,fis.close()关闭资源 
}

嵌套的try…catch语句:

try { 
	Scanner scanner = new Scanner(System.in); 
	System.out.println("请输入第1个数:"); 
	// 从键盘获取一个字符串 
	String str = scanner.next(); 
	// 将不是整数数字的字符串转换成整数, 
	//会引发NumberFormatException 
	int n1 = Integer.parseInt(str); 
	try { 
		FileInputStream fis = new FileInputStream("zkl.txt"); 	} catch (IOException ioe){
		System.out.println(ioe.getMessage()); 
	}
	System.out.println("请输入第2个数:"); 
	// 从键盘获取一个整数 
	int n2 = scanner.nextInt(); 
	System.out.println("您输入的两个数的商是:" + n1 / n2);
} catch (Exception ex) { 
	ex.printStackTrace(); 
} 
	System.out.println("程序结束!");

• 嵌套的try…catch语句可以嵌套多层,这方面没有明确的限制,但通常没有必要使用超过两层的嵌套异常处理。层次太深的嵌套异常处理会降低程序的可读性,而且也没有太大的必要,完全可以使用其他方式实现。
多异常捕获:
• 从Java 7开始,一个catch块可以捕获多种类型的异常
其中:
• 捕获多种类型的异常时,多种异常类型之间使用竖杠“|”进行间隔;
• 多异常捕获时,异常变量默认是常量,因此程序不能对该异常变量重新赋值。

 语法:
try { 
	//业务实现代码(可能发生异常) 
	...... 
}catch (异常类A [|异常类B ...|异常类N] 异常对象) { 
	//多异常捕获处理代码 
} 
	......    //可以有多个catch语句

抛出异常:
• Java中抛出异常可以使用throw或throws关键字:
• 使用throw抛出一个异常对象:当程序出现异常时,系统会自动抛出异常,
除此之外,Java也允许程序使用代码自行抛出异常,自行抛出异常使用
throw语句完成;
• 使用throws声明抛出一个异常序列:throws只能在定义方法时使用。当定
义的方法不知道如何处理所出现的异常,而该异常应由上一级调用者进行处
理,可在定义该方法时使用throws声明抛出异常。
throw抛出异常对象:
• throw语句抛出的不是异常类,而是一个异常实例对象,并且每次只能抛出
一个异常实例对象
语法:
throw 异常对象
throws声明抛出异常序列:
语法:
[访问符] <返回类型> 方法名([参数列表]) throws异常类A [,异常类B… ,异常类N]{ //方法体 }

4、自定义异常

• 自定义异常类都继承Exception或RuntimeException类

public class AgeException extends Exception { 
	public AgeException() {......}
	public AgeException(String msg) { 
		super(msg); 
	}
}

你可能感兴趣的:(Java学习)