本章目标
什么是异常
产生异常的原因
产生异常后的反应
•那么我们就必须对有可能产生的异常进行处理。
try块和catch块
try/catch块的一般形式
……
try
{
…… //监视有可能发生异常的代码段
}
catch (异常类型) //捕获发生的异常
{
…… //对异常进行处理
}
……
异 常 | 说 明 |
Exception | 异常层次结构的根类 |
RuntimeException | 许多java.lang异常的基类 |
ArithmeticException | 算术异常,如:除数为0 |
IllegalArgumentException | 方法接收到非法参数 |
ArrayIndexOutOfBoundsException | 数组下标越界 |
NullPointerException | 访问空引用 |
ClassNotFoundException | 不能加载所需的类 |
NumberFormatException | 字符串转换数字失败 |
IOException | I/O异常的根类 |
FileNotFoundException | 找不到文件 |
EOFException | 文件结束 |
异常类体系结构图
异常类体系结构说明
异常类中的常用方法 Throwable
方法原型 | 说 明 |
String getMessage() | 在Exception类中定义的方法,被继承到所有的异常类中,用于获得与异常相关的描述信息。 |
void printStackTrace() | 在Exception类中定义的方法,用于在控制台上显示有关异常的信息,不但有异常的原因,还涉及产生异常的代码行。 |
try/catch块示例
public class ExceptionDemo
{
public static void main(String[] args)
{
int a = 10, b = 0, c;
try //监视有可能出现异常的代码段
{
c = a / b;
System.out.println(c);
}
catch (ArithmeticException ae) //如果出现异常,将被捕获
{
System.out.println("除数为0。");
}
System.out.println("程序结束。");
}
}
finally块
(注:) 若存在finally块并在try/catch块中有 return() 相关语句,则
先执行finally块中的语句
再执行try/catch块中的 return() 相关语句 (面试/笔试常见问题)
try/catch/finally块示例
try {
c = a / b;
System.out.println(c);
}
catch (ArithmeticException ae) {
System.out.println("除数为0。");
}
//不论是否发生异常,finally块中的语句都会执行
finally {
System.out.println("finally块中的语句。");
}
System.out.println("程序结束。");
}
}
try/catch/finally执行流程
try/catch/finally应用模型
try
{
…… //连接到数据库的代码,有可能发生异常
…… //对数据库进行操作的代码,有可能发生异常
}
catch(SQLException sqle) //捕获数据库异常
{
…… //对捕获的异常进行处理
}
finally
{
…… //在finally块中执行关闭数据库的操作
}
多重catch块
多重catch块示例
public class ExceptionDemo {
public static void main(String[] args) {
int a, b, c;
try {
//从命令行参数获得用户输入的数字
a = Integer.parseInt(args[0]);
b = Integer.parseInt(args[1]);
c = a / b;
System.out.println(c);
}
catch (ArrayIndexOutOfBoundsException aioobe) { //捕捉数组下标越界异常
System.out.println("您没有指定命令行参数。");
}
catch (NumberFormatException nfe) { //捕捉字符串到数字转换异常
System.out.println("您输入的不是数字。");
}
catch (ArithmeticException ae) { //捕捉算术(除数为0)异常
System.out.println("除数为0。");
}
catch (Exception e) { //捕捉其它不可预测的异常
System.out.println(e.getMessage());
}
System.out.println("程序结束。");
}
}
多重catch块的注意事项
多重catch块书写顺序示例
public class ExceptionDemo {
public static void main(String[] args) {
int a, b, c;
try {
a = Integer.parseInt(args[0]);
b = Integer.parseInt(args[1]);
c = a / b;
System.out.println(c);
}
//由于Exception类的层次最高,以下的所有异常类型都是其子类,这样写将会报错
catch (Exception e) { //捕捉其它不可预测的异常
System.out.println(e.getMessage());
}
catch (ArrayIndexOutOfBoundsException aioobe) { //捕捉数组下标越界异常
System.out.println("您没有指定命令行参数。");
}
catch (NumberFormatException nfe) { //捕捉字符串到数字转换异常
System.out.println("您输入的不是数字。");
}
catch (ArithmeticException ae) { //捕捉算术(除数为0)异常
System.out.println("除数为0。");
}
System.out.println("程序结束。");
}
}
案例解析
由于Exception类的层次最高,以下的所有异常类型都是其子类,这样写将会报错,
但若将Exception类作为catch模块的最后一个模块,则报错消失
嵌套try/catch块
嵌套try/catch块示例
public class ExceptionDemo
{
public static void main(String[] args)
{
/*外层try/catch块*/
try
{
System.out.println("传递的参数是:" + args[0]);
/*嵌套try/catch块*/
try
{
int num = Integer.parseInt(args[0]);
System.out.println(num + "的平方是" + (num * num));
}
catch (NumberFormatException nfe)
{
System.out.println("您输入的不是数字。");
}
}
catch (ArrayIndexOutOfBoundsException aioobe)
{
System.out.println("您没有输入命令行参数。");
}
}
}
throw关键字
throw (异常类型的实例);
throw语句示例
public class ThrowDemo
{
public static void main(String[] args)
{
try
{
int age = Integer.parseInt(args[0]);
if (age < 0 || age > 100)
{
//创建一个异常实例,并将其手工抛出
throw (new Exception("您输入的年龄无效。"));
}
System.out.println("您的年龄是:" + age + "岁。");
}
catch (Exception e) //捕捉异常
{
//打印出异常信息
System.out.println(e.getMessage());
}
}
}
用户自定义异常
class MyException extends Exception
{
……
}
自定义异常示例
class AgeException extends Exception { //用户自定义年龄异常类
public AgeException() { //构造方法
super("年龄无效。");
}
}
public class Test {
public static void main(String[] args) {
try {
int age = Integer.parseInt(args[0]);
if (age < 0 || age > 100) {
throw (new AgeException()); //抛出自定义异常类实例
}
System.out.println("您的年龄是:" + age + "岁。");
}
catch (AgeException ae) { //捕捉自定义异常类型
System.out.println(ae.getMessage()); //打印异常信息
}
}
}
throws关键字
返回值类型 函数名(参数列表) throws异常类型
{
……
}
throws关键字示例
public class Student //定义学生类
{
private String mName; //姓名
private int mAge; //年龄
…… //其它方法,代码略
/*为姓名赋值的方法*/
public void setName(String name) { mName = name; }
/*为年龄赋值的方法,该方法有可能抛出异常*/
public void setAge(int age) throws AgeException
{
if (age < 0 || age > 100)
{
throw (new AgeException());
}
mAge = age;
}
…… //其它方法,代码略
}
调用带有throws的函数1
public class ThrowsTest {
public static void main(String[] args) {
Student std = new Student();
try {
std.setName("zhangsan");
std.setAge(24); //该方法必须放在try/catch块中
std.display();
}
catch (AgeException ae) {
System.out.println(ae.getMessage());
}
}
}
调用带有throws的函数2
示例:
public class ThrowsTest
{
public static void main(String[] args) throws AgeException
{
Student std = new Student();
std.setName("zhangsan");
std.setAge(180); //对该函数不进行监控,只是将异常继续往外抛
std.display();
}
}
Throws注意点
关于Exception的最佳实践
Example:
try{
FileReader r=new FileReader(filename);
}
catch(Exception e){ }
3.Do throw specific Exceptions (异常抛出要明确)Example:
try{
PrintWriter out=new PrintWriter(filename);
try{
//操作
}
finally{
out.close();
}
}
catch(IOException ex){
//操作
}
总结
作业