第五章 异常

一、认识异常

1.1概念

程序中出现的错误被称为异常(Exception)

1.2异常分类

JDK中定义了很多异常类,这些类对应了各种各样可能出现的异常事件,所有异常对象都是派生于Throwable类的一个实例。如果内置的异常类不能够满足需要,还可以创建自己的异常类。

异常分为ErrorException

Error:

Error类层次描述了Java运行时系统内部错误或资源耗尽错误。这类错误时我们无法控制的,同时也是非常罕见的错误。所以在编译中,不去处理这类错误。Error表名系统JVM以及处于不可恢复的崩溃状态中。我们不需要管他。打开JDK的:java.lang.error,查看他的所有子类。

Exception:

所有异常类的父类,其子类对应了各种各样可能出现的异常事件。

Runtime Exception,出现这个异常时,就一定是你的问题,可以不捕获,因为小心点这些异常时可以避免的。派生于RuntimeException的异常,是一类特殊的异常,如被0除、数组下表超范围等,其产生比较繁琐,处理麻烦,如果显示的声明或捕获将会对程序可读性和运行效率影响很大。因此由系统自动检测并将它们交给缺省的异常处理程序。这类异常通常是由编程错误导致的,因为只有小心点,这些异常都是可以避免的,所以在编写程序时,并不要求必须使用异常处理机制来处理这类异常,所有这类异常都继承自java.lang.RuntimeException。

注意:RuntimeException这个名字很容易让人产生错误影响。事实上,我们这里讨论的所有Error、Exception都是运行时发生的。

二、常见异常

2.1 ArithmeticException

除数为0的异常

public static void main(String[] args) {

int b = 0;

int i = 0;

i = b / i ;//报错行

}

Exception in thread "main" java.lang.ArithmeticException: / by zero

at com.sxt.Test0823.A.main(A.java:7)

2.2 NullPointerException

当程序访问一个空对象的成员变量或方法,访问一个空数组的成员时发生。怎么处理?

public static void main(String[] args) {

A a = null;

a.getClass();//报错行

}

Exception in thread "main" java.lang.NullPointerException

at com.sxt.Test0823.A.main(A.java:6)

2.3 ClassCastException

强制转换时类型错误,不能强转时报错,比如以下把猫转成狗

public class Animal {

public static void main(String[] args) {

Animal d1 = new Dog();

Animal c2 = new Cat();

Dog d = (Dog)d1;

Dog c = (Dog)c2;//报错行

}

}

class Dog extends Animal

}

class Cat extends Animal{

}

Exception in thread "main" java.lang.ClassCastException: com.sxt.Test0823.Cat cannot be cast to com.sxt.Test0823.Dog

at com.sxt.Test0823.Animal.main(Animal.java:8)

2.4 ArrayIndexOutOfBoundsException

访问的元素下标超过数组的长度-下标越界

int[] a = {1,2,3};

System.out.println(a[4]);//报错行

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4

at com.sxt.Test0823.Animal.main(Animal.java:6)

 

2.5 NumberFormatException

数字格式异常

String str = "1234abcf";

Integer i = new Integer(str);

Exception in thread "main" java.lang.NumberFormatException: For input string: "1234abcf"

at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)

at java.lang.Integer.parseInt(Integer.java:456)

at java.lang.Integer.<init>(Integer.java:620)

at com.sxt.Test0823.Animal.main(Animal.java:6)

所有不是Runtime Exception的异常,统称为Checked Exception,又被称为“已检查异常”。这类异常的产生不是程序本身的问题,通常由外界因素造成的。为了预防这些异常产生时,造成程序的中断或得到不正确的结果,Java要求编写可能产生这类异常的程序代码时,一定要去做异常的处理。

三、异常的处理办法一:捕获异常

3.1 try

try语句指定了一段代码,该段代码就是一次捕获处理的范围。在执行过程中,当任意一条语句产生异常时,就会跳过该段中后面的代码。代码中可能会产生并抛出一种或几种类型的异常对象,它后面的catch语句要分别对这些异常做对应的处理。一个try语句必须有至少一个catxh语句或一个finally语句块。

注:当异常处理的代码执行结束以后,是不会回到try语句去执行尚未执行的代码。

3.2 catch

每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象。

常用方法:toString()方法,显示异常的类名和产生异常的原因。getMessage()方法,只显示产生异常的原因,但不显示类名。printStackTrace()方法,用来跟踪异常事件发生时堆栈的内容。这些方法均继承自Throwable类。

catch捕获异常时的补货顺序:如果异常类之间有继承关系,在顺序安排上需注意。越是顶层的类,越放在下面,再补然就直接把多余的catch省略掉。

3.3 finally

有些语句,不管是否发生了异常,都必须要执行,那么久可以把这样的语句放到finally语句块中。通常finally中关闭程序块已打开的资源。比如文件流、释放数据库链接等。

3.4经典代码示例

	public static void main(String[] args) {
		FileReader reader = null;
		try{
			reader = new FileReader("d:/a.txt");
			char temp = (char) reader.read();
			System.out.println("读出的内容:" + temp);
		}catch(FileNotFoundException e) {
			System.out.println("文件没有找到!!");
			e.printStackTrace();
		}catch(IOException e) {
			e.printStackTrace();
			System.out.println("文件读取错误!");
		}finally {
			System.out.println(" 不管有没有异常,我肯定会被执行!");
			try {
				reader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

四、异常的处理办法二:声明异常throws

当Checked Exception产生时,不一定立刻处理它,可以再把异常Throws出去。

在方法中使用try-catch-finally由这个方法处理异常。在一些情况下,当前方法并不需要处理发生的异常,而是向上传递给调用它的方法处理。如果一个方法中可能产生某种异常,但是并不能确定如何处理这种异常,则应根据异常规范在方法的首部声明该方法可能抛出的异常。如果一个方法抛出多个已检查异常,就必须在方法的首部列出所有的异常,之间以逗号隔开。

经典代码:


import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class FileTest {
	public static void main(String[] args) {
		try {
			readFile("d:/a.txt");
		} catch (FileNotFoundException e) {
			System.out.println("所需要的文件不存在!");
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("文件读写出错误!");
			e.printStackTrace();
		}
	}
	public static void readFile(String fileName) throws IOException {
		FileReader in = new FileReader(fileName);
		try {
			int tem = 0;
			tem = in.read();
			while (tem != -1) {
				System.out.println((char) tem);
				tem = in.read();
			}
		} finally {
			in.close();
		}
	}
}

方法重写中声明异常原则:子类声明的异常范围不能超过父类声明的范围。包含如下意思:父类没有声明异常,子类也不能。不可抛出原有方法抛出异常类的父类或上层类。抛出的异常类型的数目不可以比原有的方法抛出的还多(不是指个数)。

五、异常的处理办法三:手动抛出异常throw

Java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可根据需要手工创建并抛出。在捕获一个异常前,必须有一段代码先生成异常对象并把它抛出。这个过程我们可以手工做,也可以由JRE来实现,但是他们调用的都是throw子句。

对于一个已经存在的异常类,抛出该类异常对象过程如下:找到一个合适的异常类,创建一个该类的对象,将对象抛出。

public class FileTest {
	public static void main(String[] args) {
		File f = new File("c:/tt.txt");
		if (!f.exists()) {
			try {
				throw new FileNotFoundException("File can't be found!");
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}
	}
}

六、自定义异常

在程序中,可能会遇到任何标准异常类都没有充分的描述清楚的问题,这种情况下可以创建自己的异常类。从Exception类或者它的子类派生一个子类即可。

习惯上,定义的类应该包含2个构造器:一个是默认的构造器,另一个是带有详细信息的构造器。

package com.sxt.Test0823;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

class IllegalAgeException extends Exception {
	public IllegalAgeException() {
	}
	public IllegalAgeException(String msg) {
		super(msg);
	}
}
class Person {
	private String name;
	private int age;
	public void setName(String name){
		this.name = name;
	}
	public void setAge(int age){
		if (age < 0)
			throw new IllegalAgeException("人的年龄不应该为负数");
		this.age = age;
	}

	public String toString(){
		return "name is " + name + " and age is " + age;
	}
}
public class MyExceptionTest{
	public static void main(String[] args){
		Person p = new Person();
		try {
			p.setName("Lincoln");
			p.setAge(-1);
		} catch (IllegalAgeException e) {
		e.printStackTrace();
			System.exit(-1);
		}
		System.out.println(p);
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值