异常处理
这几天又看了一下异常处理,记录一下书和视频里面的一些知识点,有什么不对或者漏掉的地方欢迎指出。
关于异常的常用的5个关键字:
1、try:里面放置可能引发异常的代码
2、catch:接异常类型和代码(个人感觉和if语句有点像)
3、finally:回收在try里打开的资源(就是确保finally里的代码一定会执行)
4、throw:抛出一个异常(个人感觉是让人更容易看懂)
5、throws:声明可能抛出的异常(让别人解决)
try是必须的,但是catch和finally是可以2选1的,即catch没有则finally有,finally没有则catch有,也可以2者一起出现。
可以有多个catch块,但是捕获父类异常的catch块要在子类异常的catch块之后。
catch在try后,finally在catch后。
try…catch的使用实例:
public class Yichang1 {
public static void main(String[] args) {
int x,y;
try{
x=0;
y=5/x;//若此处出现错误则后续代码不会继续判断异常,输出”发生了异常,除数不能为0“
int[] arr = {1,2,3};//在一组代码块多组异常类型时会判断时哪种类型然后输出对应异常
System.out.println(arr[3]);//发生了异常,数组下标越界
System.out.println("需要检测的程序");//无错误输出此语句
}catch(ArithmeticException e){
System.out.println("发生了异常,除数不能为0");//有错误输出此语句
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("发生了异常,数组下标越界");
}
System.out.println("程序运行结束");
}
}
在一个try对应多个catch时,会自动判断发生的错误去选择对应的catch,而当执行到出错的语句后后面的语句将不再执行,上述代码中的数组部分就不会执行。
finally的实例:
/*
e.toString():获得异常种类和错误信息
e.getMessage():获得错误信息
e.printStackTrace():在控制台打印出异常种类,错误信息和出错位置
Integer.parseInt():将字符串转化为整数
*/
public class FinallyTest {
public static void main(String[] args) {
try{
int age = Integer.parseInt("88L");//输入类型出现错误”88L“
System.out.println("输出1");
}catch(NumberFormatException e){
//int b = 8/0;
System.out.println("请输入整数年龄");
System.out.println("错误"+e.getMessage());//错误For input string: "88L"
System.out.println(e.toString());//java.lang.NumberFormatException: For input string: "88L"
}finally{
System.out.println("输出2");
}
System.out.println("输出3");
}
}
上述代码中的finally里的代码是一定会执行的
throw和throws:
1、throw关键字必须在方法内部
2、throw后new的对象必须是Exception或者是Exception的子类对象
3、throw抛出指定的的异常对象,我们就必须处理这个异常对象
throw后创建的是RuntimeException或者是RuntimeException的子类对象,我们可以不处理,默认交给jvm处理(打印异常对象,中断程序)
throw后创建的是编译异常(写代码时报错),我们就必须处理这个异常,要么throws,要么try...catch...
*/
public class ThrowTest {
public static void main(String[] args) {
//int[] arr = null;
int[] arr = new int[5];
int e = getElement(arr,5);
System.out.println(e);
}
/*
定义一个方法,获取数组指定索引处的元素
参数:
int[] arr
int index
必须先对方法传递过来的参数进行合法性校验
如果参数不合法,那么我们就必须使用抛出异常的方式,告知调用者,传递的参数有问题
注意:
NullPointerException是一个运行期异常,不用处理,交给jvm处理
*/
public static int getElement(int[] arr,int index){
//对参数数组进行校验,如果arr的值是null,抛出空指针异常
if(arr == null){
throw new NullPointerException("传递的数组是null");//Exception in thread "main" java.lang.NullPointerException: 传递的数组是null
}
//可以对index进行合法性校验,index不在索引范围内,抛出越界异常,告知调用者
if(index<0 || index > arr.length-1){
throw new ArrayIndexOutOfBoundsException("传递的索引超出了数组的使用范围");//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 传递的索引超出了数组的使用范围
}
int ele = arr[index];
return ele;
}
}
/*
throws:说明这里有异常,处理的第一种方式,让别人处理,最终交给jvm处理
throws会把异常声明抛出给调用者处理
使用格式:方法声明时使用(声明异常必须是Exception或其子类对象)
修饰符 返回值类型 方法名(参数列表) throws xxxException,yyyException,...{
throw new xxxException("产生原因");
throw new yyyException("产生原因");
...
}
抛出的多个异常有子父类关系,直接声明父类即可
*/
import java.io.FileNotFoundException;
import java.io.IOException;
public class ThrowsTest {
//FileNotFoundException 继承了 IOException,可以只写IOException,所有异常都是Exception的子类
public static void main(String[] args) throws FileNotFoundException,IOException {
//readFile("c:\\b.txt");Exception in thread "main" java.io.FileNotFoundException: 文件找不到,传递的文件路径不是:c:\a.txt
//readFile("c:\\a.txt");//路径没有问题,读取文件
readFile("c:\\a.txa");//Exception in thread "main" java.io.FileNotFoundException: 文件找不到,传递的文件路径不是:c:\a.txt
}
/*
定义一个方法对传递文件的路径进行合法性判断
如果不是"c:\\a.txt",那么我们就抛出文件找不到对象的异常,告知方法调用者
注意:
FileNotFoundException是编译异常,就必须处理这个异常
可以用throws或者try...catch
*/
public static void readFile(String fileName) throws FileNotFoundException,IOException{
if(!fileName.equals("c:\\a.txt")){
throw new FileNotFoundException("文件找不到,传递的文件路径不是:c:\\a.txt");
}
//不是.txt结尾,抛出io异常,后缀名不对
if(!fileName.equals(".txt")){
throw new IOException("文件的后缀名不对");
}
System.out.println("路径没有问题,读取文件");
}
}
我认为比较重要的细节就是异常的子类与父类同时出现时可以在throws后只声明父类。
如果是编译异常就一定要用throws或者try…catch处理,运行期异常直接让JVM处理即可。