1.异常处理体系结构
2.从程序执行过程看编译时异常和运行时异常
》编译时异常:执行javac.exe命令时,可能出现的异常
》运行时异常:执行java.exe命令时,出现的异常
3.常见的异常类型,请举例说明:
@Test
public void test1() {
try{String str="abc";
int num= Integer.parseInt(str);}
catch(NumberFormatException e) {
e.printStackTrace();
}
System.out.println("hello test1");
}
//NullPointerException
@Test
public void test2() {
try{String str="hello";
str=null;
System.out.println(str.length());
}
catch(NullPointerException e) {
e.printStackTrace();}
System.out.println("hello test2");
}
//ArithmeticException
@Test
public void test3() {
try {
int i=10;
int j=0;
int result =i/j;
}catch (ArithmeticException e) {
e.printStackTrace();
}
} //classCastException
@Test
public void test4() {
try{Object o ="hello";
int i= (int)o;
System.out.println(o);}
catch(ClassCastException e) {
e.printStackTrace();
}
}
}
4.异常处理的抓抛模型
过程一:"抛":程序在正常执行过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象。并将此对象抛出,一旦抛出对象后,其后的代码就不再执行。
》关于异常对象的产生:1)系统自动生成的异常对象 2)手动生成的一个异常对象,并抛出(throw)
过程二:"抓":可以理解为 异常处理的方式1)try-catch-finally 2)throws
5.try-catch-finally 使用:
1结构:
try{
可能出现异常的代码
}catch(异常类型1 异常对象1){
异常处理1
}
catch(异常类型2 异常对象2){
异常处理2
}
catch(异常类型3 异常对象3){
异常处理3
}
...
finally{
//一定会执行的代码
}
说明:
》finally时可选的
》使用try将可能出现异常的代码包装起来,在执行过程中,一旦出现异常,就会生成
一个对应异常类的对象,根据此对象的类型,去catch中进行匹配
》一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常处理。一旦处理完成
就跳出当前try-catch结构(在没写finally的情况。继续执行其后的代码)
》catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓,
catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类上面,否则报错。
》常用的异常对象处理方式1)String getMessage() 2)printStackTrace()
》在try结构中声明的变量,在出了try结构后,就不能在被调用
》try-catch-finally 结构可以嵌套
总结:如何看待代码中的编译时异常和运行时异常?
1) 使用try-catch-finally 处理编译时异常,是得程序在编译时就不再报错,但是运行
时仍可能报错。相当于使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现
2)开发中,由于运行时异常比较常见,所以我们通常不针对运行时异常编写try-catch-finally了。针对编译时异常,一定要考虑异常处理
2 finally在说明:
》finally是可省略的
》finally中声明的是一定被执行的代码,即使catch中又出现异常了。try中的return语句。catch中的return语句等情况。
》像数据库连接、输入输出流、网络编程socket等资源,jvm是不能自动回收的,我们需要自己手动的进行资源的释放。此时的资源释放,就需要声明在finally中
3.异常处理方式二:
throws+ 异常类型 写在方法的声明处。指明此方法执行时,可能会抛出的异常类型。一旦当方法体执行时,出现异常,仍会在异常代码出生成一个异常类的对象,此对象满足throws后异常类型时,就会被抛出。异常代码的后续代码,就不再被执行。
4.对比两种处理异常方式
》try-catch-finally:真正的将异常给处理掉了。throws的方式只是将异常抛给了方法的调用者,并没有真正将异常处理掉
5.体会开发中应该如何选择两种处理方式?
》如果父类中被重写的方法没throws方式处理异常,则子类重写的方法也不能使用throws,意味着如果子类重写的方法出现异常,必须使用try-catch-finally处理
》执行的方法a中,先后又调用了另外的几个方法,这几个方法递进关系执行的。我们建议这几个方法使用throws的方式进行处理。而执行的方法a可以考虑使用try-catch-finally处理
6 .throw 与throws的区别:
》throw 表示抛出一个异常类的对象,生成异常对象的过程,声明在方法体内
》throws 属于异常处理的一种方式,声明在方法的声明处
例
class Student{
private int id ;
public void regist(int id )throws Exception {
if(id>0) {
this.id=id;
}else {
throw new Exception("你输入的数据非法!");
}
}
@Override
public String toString() {
return "Student [id=" + id + "]";
}
}
7.自定义异常类:
如何定义异常类?
》继承现有的异常结构,RuntimeException , Exception
》提供全局变量serialVersionUID
》提供重载的构造器
例:自定义异常类:MyException
public class MyException extends Exception {
static final long serialVersionUID = -33875163124229948L;
public MyException() {}
public MyException(String msg) {
super(msg);
}
}
8.综合例题:定义EcmDef类,实现从控制台输入2个数并返回结果,使用异常处理
public class EcmDef {
public static void main(String[] args) {
try {
int i =Integer.parseInt(args[0]);
int j =Integer.parseInt(args[1]);
int result =ecm(i,j);
}catch(NumberFormatException e) {
System.out.println("数据类型不一致");
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("参数个数不一致");
}catch(ArithmeticException e) {
System.out.println("除0");
}catch(EcDef e) {
System.out.println(e.getMessage());
}
}
public static int ecm(int i,int j) throws EcDef {
if(i<0||j<0) {
throw new EcDef("分子或分母为负数");
}
return i/j;
}
}
// 自定义异常类
public class EcDef extends Exception {
static final long serialVersionUID = -33875193124229948L;
public EcDef() {}
public EcDef(String msg) {
super(msg);
}
}