异常
异常处理
例:
public class Demo{public static void main(String[] args) {System.out.println("开始");method();System.out.println("结束");}public static void method(){int[] arr={1,2,3};System.out.println(arr[3]);//数组索引越界,报错}
}
输出:
异常处理:
public class Demo{public static void main(String[] args) {System.out.println("开始");method();System.out.println("结束");}public static void method(){try{int[] arr={1,2,3};System.out.println(arr[3]);}catch (ArrayIndexOutOfBoundsException e){System.out.println("你访问的数组索引不存在");}}
}
输出:
public class Demo{public static void main(String[] args) {System.out.println("开始");method();System.out.println("结束");}public static void method(){try {int[] arr={1,2,3};System.out.println(arr[3]);}catch (ArrayIndexOutOfBoundsException e){e.printStackTrace();}}
}
程序会往下执行,并且指出错误。
输出:
/*
一、异常的处理:抓抛模型
过程一:“抛” 程序正常执行时,一旦出现异常,就会在异常代码处生成
一个对应异常类的对象并抛出。一旦抛出对象以后,后面的代码就不再执行过程二:“抓” 可以理解为异常的处理方式:1.try-catch-finally 2.throws
二、try-catch-finally的使用
try{//可能出现异常的代码
}catch(异常类型1 变量名1){//处理异常的方式1
}catch(异常类型2 变量名2){//处理异常的方式2
}...可以有多个catch
finally{//一定会执行的代码
}说明:
1.finally是可有可没有的,使用try将可能出现异常代码包装起来在执行过程中,
一旦出现异常,就会生成一个对应异常类的对象根据次对象的类型,去catch中进行匹配。
2.一旦try中的异常对象匹配到某个catch时,就进入catch中进行异常的处理,处理完成后,
跳出try-catch结构(没有finally时的情况)。继续执行后面的代码。
3.catch中的异常类型如果没有字父类关系,则谁声明在前都无所谓若满足子父类关系,则要求子类声明在父类上面,否则报错。
4.常用的异常对象处理方式:①String getMessage() ②printStackTrace()这个常用*/
public class Demo1 {public static void main(String[] args) {String str="abc";int num=0;try{num=Integer.parseInt(str);}catch (NumberFormatException e){System.out.println("出现数值转换异常");}System.out.println("11111");}
}
使用try-catch-finally处理编译时异常,则编译时不报错,但运行时仍可能报错
相当于将编译时可能出现的异常,延迟到运行时出现。
finally的使用:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;/*
1.finally是可有可没有的
2.finally中的代码一定会执行,即使catch中又出现异常,catch或try中有return语句
3.像数据库连接、输入输出流、网络编程Socket等资源,JVM是不能自动回收的我们需要自己手动进行资源的释放。此时的资源释放就需要声明再finally中。
4.try-catch-finally结构可以相互嵌套*/
public class Demo {public static void main(String[] args) {FileInputStream fis=null;try {File file=new File("hello.txt");fis=new FileInputStream(file);int data=fis.read();while (data!=-1){System.out.println((char)data);data=fis.read();}}catch (FileNotFoundException e){e.printStackTrace();}catch (IOException e){e.printStackTrace();}finally {//嵌套使用try-catch-finallytry {fis.close();} catch (IOException e) {e.printStackTrace();}}}public void test(){int num=0;String str="aa";try{num=Integer.parseInt(str);}catch (NumberFormatException e){System.out.println("数值类型转换异常");}finally {System.out.println("一定执行的内容");}}
}public class Demo1 {public static void main(String[] args) {try{int a=10;int b=0;System.out.println(a/b);}catch (ArithmeticException e){e.getStackTrace();int[] arr=new int[10];//数组越界,异常,导致程序停止System.out.println(arr[10]);}finally {//finally中的代码仍会执行System.out.println("必须执行的代码");}}public int test1(){//实际返回的值是finally中的return 2try{int a=10,b=0;System.out.println(a/b);}catch (ArithmeticException e){return 1;}finally {return 2;}}
}
其实在实际开发中,由于运行时异常比较常见,所以不去做try-catch处理,编译时异常需要处理。
当finally前面出现System.exit(0)时,(括号内不一定是0,也可以说是1)程序终止,所以finally语句不会执行。
Throwable的成员方法
e.printStackTrace()输出的异常信息最全,所以一般使用这个。
编译时异常和运行时异常的区别
也被称为受检异常和非受检异常。
所有的RuntimeException类及其子类被称为运行时异常,其他的异常都是编译时异常。
编译时异常: 必须显示处理,否则程序就会发生错误,无法通过编译。
显示处理:
编译报错只是提示你有可能会出现错误,但不一定真的出现错误,显示处理后该程序没有错误。
运行时异常: 无需显示处理,也可以和编译时异常一样处理。
处理异常之throws
虽然try…catch…可以对异常进行处理,但并不是所有的情况我们都有权限进行异常的处理。也就是说有些时候可能出现的异常是我们处理不了的,这个时候咋办?
针对该情况,java提供了throws的处理方案。
无论是编译时异常还是运行时异常,使用throws都是抛开异常,要想程序继续往下执行,还是要用try…catch…处理,由调用者来处理。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;/*
异常处理的方式二:throws+异常类型
1.“throws+异常类型“写在方法的声明处。执行此方法时可能会抛出异常类型
一旦方法执行时出现异常,仍会在异常代码处生成一个异常类的对象。次方对象满足throws
后的异常类型时,就会被抛出。
2.一旦抛出异常后,后面的代码不再执行。*/
public class Demo {public static void main(String[] args) {//main中处理异常try{test2();}catch (FileNotFoundException e){e.printStackTrace();}catch (IOException e){e.printStackTrace();}}public static void test2() throws IOException {//该方法调用test() 也处理不了异常,抛给maintest();}public static void test() throws FileNotFoundException,IOException{//该方法处理不了这个异常,抛给test2File file=new File("hello.txt");FileInputStream fis=new FileInputStream(file);int data=fis.read();while (data!=-1){System.out.println((char)data);data=fis.read();}fis.close();}
}
try-catch-finally:真正的将异常给处理掉了。而throws只是将异常抛给了方法的调用者。并没有真正将异常处理掉。
自定义异常类
import java.util.Scanner;public class EcmDef{public static void main(String[] args) {String str1,str2;Scanner s=new Scanner(System.in);str1=s.nextLine();str2=s.nextLine();int i=0,j=0;try{i=Integer.parseInt(str1);j=Integer.parseInt(str2);int result=ecm(i,j);System.out.println(result);}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;}
}
//自定义异常类
class EcDef extends RuntimeException{//自定义一个序列号static final long serialVersionUID=-156461646L;public EcDef(){}public EcDef(String msg){super(msg);}
}
重写方法的异常抛出
import java.io.FileNotFoundException;
import java.io.IOException;/*
重写方法异常抛出的规则
1.子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型。
2.如果父类没有抛出异常,那么子类也不能抛出异常*/
public class Demo {public static void main(String[] args) {Demo test=new Demo();test.display(new SubClass());//多态}public void display(Super s){try{s.method();}catch (IOException e){e.printStackTrace();}}
}
class Super{public void method() throws IOException{}
}
class SubClass extends Super{public void method() throws FileNotFoundException{}
}
开发中如何选择使用try-catch-finally还是throws?
1.若父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,意味着若子类重写的方法中有异常,必须使用try-catch-finally处理。
2.在执行的方法a中,先后又调用了另外几个方法,且这几个方法是递进关系执行的,建议这几个方法使用throws的方式进行处理。而执行的方法a可以考虑使用try-catch-finally方法进行处理。
手动抛出异常
关于异常对象的产生:
1.系统自动生成的异常对象
2.手动生成一个异常对象,并抛出(throw)
throws和throw的区别
throw是手动异常对象的产生,throws是异常处理的一种方式。
先执行finally语句再throw手动抛出异常。