1.异常的概念
在程序运行过程中出现的错误称为异常
(1)异常是什么
第一、异常模拟的是现实世界中“不正常的事件
第二、java中采用类去模拟异常
第三、类是可以创建对象的
(2)异常机制的作用
java语言为我们提供了一种完善的异常处理机制,作用是程序发生异常事件之后为我们输出了详细的信息,
程序员通过这个信息,可以对程序进行处理,使程序更加健壮
2.异常的层次结构
所有Exception的直接子类都是“编译时异常”,其余都是RuntimeException(运行时异常)
所有的编译时异常,要求程序员在程序编写阶段必须对它进行处理,如果不处理的话编译无法通过。
处理异常有两种方式,捕捉和声明抛出。捕捉,try…catch…,声明抛出就是在方法声明的位置上使用
throws关键字抛出异常
所有的RuntimeException的子类都是运行时异常,运行时异常程序员在编写阶段不需要对它进行处理
编译时异常对应发生几率比较高的异常,运行时异常对应发生几率比较低的异常
3.处理异常的两种方式
(1)声明抛出
在方法声明的位置上使用throws关键字向上抛出异常
import java.io.;
public class ExceptionTest03{
public static void main(String[] args) throws FileNotFoundException{
public static void main(String[] args) throws IOException{
public static void main(String[] args) throws Exception{
//创建文件输入流,读取文件
//java编译器为什么知道以下的代码运行过程中可能出现异常?
//java编译器不是那么智能,因为FileInputStream这个构造方法在声明的位置上使用了throws FileNotFoundException;
FileInputStream fis = new FileInputStream(“c:/ab.txt”);
}
}
//编译不通过
/
.\ExceptionTest03.java:4: 错误: 未报告的异常错误FileNotFoundException; 必须对其进行捕获或声明以便抛出
FileInputStream fis = new FileInputStream(“c:/ab.txt”);
^
1 个错误
*/
//深入throws
import java.io.*;
public class ExceptionTest04{
public static void main(String[] args) throws FileNotFoundException{
m1();
//使用throws不是真正的处理异常而是推卸责任
//谁调用的就会抛给谁
//m1方法如果抛出异常,因为采用的是上抛,给了JVM,JVM遇到异常退出,下面代码不会执行
System.out.println();
}
public static void m1() throws FileNotFoundException{
m2();
}
public static void m2() throws FileNotFoundException{
m3();
}
public static void m3() throws FileNotFoundException{
FileInputStream fis = new FileInputStream("c:/ab.txt");
}
}
(2)捕捉try…catch
语法:
try{
可能出现异常的代码;
}catch(异常类型1 变量){
处理异常的代码;
}catch(异常类型2 变量){
处理异常的代码;
}…
catch可以写多个,但是必须从上到下,从小到大捕捉
catch语句块最多执行一个语句块
try…catch…捕捉到异常后,try语句块的剩余语句不再执行,执行相应catch语句块的内容后,继续向下执行其余的语句块
import java.io.*;
public class ExceptionTets05{
public static void main(){
try{
FileInputStream fis = new FileInputStream("c:/ab.txt");
fis.read();
}catch(FileNotFoundException e){
}catch(IOException e){
}
}
}
4.关于getMessage和printStackTrace方法的应用
public class ExceptionTest07{
public static void main(String[] args){
try{
FileInputStream fis = new FileInputStream(“c:/abc.txt”)
}catch(FileNotFoundException e){
//打印异常堆栈信息
//一般情况下用该方式去调试程序
e.printStachTrace();
String msg = e.getMessage();
System.out.println(msg);
}
}
}
4.finally语句块
(1)finally语句块可以直接和try语句联用。try…finally…
(2)try…catch…finally也可以
(3)在finally语句块中的代码是一定会执行的
public class ExceptionTest08{
public static void main(String[] args){
try{
System.out.println(“ABC”);
return;
}finally{
System.out.println(“Test”); //结果是ABC,TEST,即使return
}
try{
FileInputStream fis = new FileInputStream("c:/abc.txt")
System.out.println(“TTTT”);
}finally{
System.out.println(“AAAA”);
}
//只要在执行finally语句块之前退出了JVM,则finally语句块不会执行
try{
//退出JVM
System.exit(0);
}finally{
//不会执行
System.out.println(“AAAA”);
}
}
}
深入finally语句块
public class ExceptionTest09{
public static void main(String[] args){
int i = m1();
System.out.println(i); //10
}
public static int m1(){
int i = 10;
try{
return i;
}finally{
i++;
System.out.println(“m1的i=”+i); //11
}
}
}
finallly语句块是一定会执行的,所以在程序中为了保证某资源一定会释放,一般在finally中释放资源
import java.io.*;
public class ExceptionTest10{
public static void main(String[] args){
//因为try和finally的数据不共用,因此必须在外部声明
FileInputStream fis = null;
try{
fis = FileInputStream("ExceptionTest10.java");
}catch(FileNotFoundException e){
e.printStachTrace();
}finally{
//为了保证资源一定会释放
if(fis != null){
try{
fis.close();
}catch(IOException e){
e.printStachTrace();
}
}
}
}
}
5.自定义异常
//自定义"无效名字"异常
(1)编译时异常直接继承Excaption
(2)运行时异常直接继承RuntimeException
public IlleaglNameException extends Exception{
//定义异常一般提供两个构造方法
public IlleaglNameException(){}
public IlleaglNameException(String msg){
super(msg);
}
}
//顾客相关的业务
public class CustomService{
public void register(String name) throws IlleaglNameException{
if(name.length()<6){
//异常
//创建异常对象
IlleaglNameException e = new IlleaglNameException(“用户名长度不能少于6位”);
//手动抛出异常
throw e;
//或者
throw new IlleaglNameException("用户名长度不能少于6位");
}
//代码执行到此处,证明用户名合法
System.out.println("注册成功");
}
}
public class Test{
public static void main(String[] args){
String username = “jack”;
CustomService cs = new CustomService();
try{
cs.register(username);
}catch(IlleaglNameException e){
System.out.println(e.getMessage());
}
}
}
6.方法的覆盖与异常
重写的方法不能比被重写的方法抛出更宽泛的异常
/*
class A{
public void m1(){}
}
class B extends A{
//子类无法抛出比父类更多的异常
public void m1() throws Exception{}
}
*/
/*
class A{
public void m1() throws FileNotFoundException{}
}
class B extends A{
//子类无法抛出比父类更多的异常
public void m1() throws IOException{}
}
*/