异常处理

异常处理

什么异常?

在生活中:平时上下班都平常,今天上班的时候,路上有一起车祸,导致你上班迟到。

所谓异常:就出现了出乎意料的事情。

在代码里:所谓异常也是程序在编写或者运行过程中出现了出乎意料的事情。

比如:你做3D彩票系统,你提示别人输入数字,结果别人输入的还是字符串,出现了crash。

再比如:你把元素放到ArrayList中,但是你给的下标超出了元素的个数,程序也会出现异常。

异常的分类

在Java中异常一共分为2大类:Error、Exception。

早整个异常体系了,有如下继承关系

Throwable 它是所有异常和错误的父类。

​ Error:它是Throwable的子类。 代表错误,一般指的是系统错误,或者虚拟机错误。错误例如:内存不足,JVM出现问题,也属于错误。错误往往不是程序员能解决的,所以无需解决。

​ Exception:也是Throwable的子类。 代表异常,异常分为2类,运行期异常,另外一类叫非运行期异常。

​ RunTimeException:运行期异常。编译期并不会报错,运行的时候才会报错。

​ 其他:非运行期异常。编译期就报错。错误不处理,无法运行程序。

Error的示例
public static void main(String[] args) throws FileNotFoundException {
		long[] arr = new long[1024*1024*100*4];//内存不足的错误
	}
}

Exception的示例
RunTimeException示例
public class Test {

	public static void main(String[] args) throws FileNotFoundException {
		
		int[] arr1 = {1,2,3,4};
		System.out.println(arr1[4]);//运行期异常, 数组下标越界
		
		int m = 100;
		int n = 0;
		System.out.println(m / n );//运行期异常, 除数为0的异常
	}

}
非运行期异常的示例
public class Test {

	public static void main(String[] args) throws FileNotFoundException {	
		FileInputStream fis = new FileInputStream("C:\\Users\\neal\\Desktop\\a.docx");//非运行期异常,文件没有找到异常
	}
}

异常的处理

如果程序出现了异常,但是并没有对异常进行处理,虚拟机就会处理异常。虚拟机的处理方式就是结束出现异常的线程。在多线程的环境下,如果A线程出现了异常,只是结束A线程的运行,B,C等线程都能正常的执行。

异常的处理有2种方式:

方式一:try …catch…finally 直接处理异常

方式二:thows 抛出异常,交给这个方法的调用者处理。

如果有一个a方法,a方法内部可能出现异常,但是a方法内部通过thows抛出了异常,相当于告诉调用a方法的那段代码,a方法有可能有异常,但是我没有处理,交给调用a方法的代码去处理。

try…catch…finally

把有可能出现异常的代码,放到try代码块中。try的作用是试图找到和发现异常。一旦try代码块中有异常,会执行对应的catch代码块。

public class Test {

	public static void main(String[] args) {
		
		int m = 100;
		int n = 0;
		int result = 0;
		int[] arr = {1,2,3};
		try {
			result = m / n;
			int num = arr[3];
		}catch(ArithmeticException e) {
//			System.out.println(e.getMessage());
//			System.out.println(e.getLocalizedMessage());
//			System.out.println(e);
			n = 1;
			result = m / n;
		}catch(ArrayIndexOutOfBoundsException e) {
			int num = arr[0];
			System.out.println(num);
		}
		
		System.out.println(result);
	}
}

try中一旦发现异常,就会立即跳转到对应的catch块中进行异常处理。try中没有执行到的代码,不再执行。换句话说,try只能捕获第一个异常。

如果有多个异常,写多个try…catch…finally代码段。

多个catch是可以合并的。只需要把catch中的异常范围写的更大即可。

因为try一旦发现异常,就立即进入了catch块,导致try中的部分代码没法执行。异常处理提供了finally来解决这个问题。

finally也是一个代码块,无论try有没有异常,finally中的代码都会执行。

情形一:try中没有出现异常,catch不执行,finally执行。

情形二:try中出现异常,执行对应的catch,catch执行以后,执行finally。

所以可以把必须要执行的代码写在finally里面。

public class Test {

	public static void main(String[] args) {
		
		int m = 100;
		int n = 10;
		int result = 0;
		int[] arr = {1,2,3};
		try {
			result = m / n;
			int num = arr[2];
		}catch(RuntimeException e) {
//			System.out.println(e.getMessage());
//			System.out.println(e.getLocalizedMessage());
//			System.out.println(e);
			n = 1;
			result = m / n;
		}finally{
			System.out.println("我是finally");
		}
		
		System.out.println(result);
	}
}

小节

Java中异常分为Error和Exception两类

Exception分为RuntimeException和非RuntimeException。

try…catch…finally可以处理异常。

​ try中写,可能出现的异常。

​ catch中写,如何处理异常。异常是可以分开捕获,异常还可以合起来捕获。

​ finally中写那些一定要执行的代码。

throws

throws是第二种异常处理的方式。这种处理方式,相当于自己没有做出处理,把处理的事情交给了它的上一级(调用者)来处理。

为什么要使用throws?

一般调用者更清楚异常出来以后应该做什么事情。

throws如何使用?

当有异常存在的时候,如果这个异常不适合你处理,适合你的上层(调用者)处理,你应该把这个异常处理的权利交给你的上层。上层就会得到这个异常,它有2种选择:第一,通过try…catch…finally处理异常,第二,继续上抛,抛给它的调用者。

public class TestException {

	public static void main(String[] args) throws FileNotFoundException {
		
		//readFile("C:\\Users\\neal\\Desktop\\微信小程序.md");
//		try {
//			readFile2("C:\\Users\\neal\\Desktop\\微信小程序.md");
//		} catch (FileNotFoundException e) {
//			
//		}
		
		readFile2("C:\\Users\\neal\\Desktop\\微信小程序.md");
		
	}
	
	public static void readFile2(String filePath) throws FileNotFoundException {
		FileInputStream fis = new FileInputStream(filePath);
		System.out.println(fis);
	}
	
	public static void readFile(String filePath) {
		try {
			FileInputStream fis = new FileInputStream(filePath);
		} catch (FileNotFoundException e) {
			System.out.println("打开文件失败,文件不存在");
			e.printStackTrace();
		}
		
	}
}
throws的特点

throws本质上是在做一个声明,它在告诉调用者,我内部的代码可能有某种异常产生。用于警醒调用者。

throws出现在方法参数列表的后面,throws 后面跟着的是具体的异常的类名。

补充一句,throws 后面的异常可以是多个,多个异常之间用逗号隔开。

再补充一句,throws后面的异常可以合并为父异常。

throw

throw是个动词,它的作用是抛出一个具体的异常。

用法:throw 异常对象;

你平时代码里出错时控制台打印的这些异常信息,都是系统API里提前写了throw e的原因。

throw 和throws区别
  1. throw是用来抛出异常的。后面跟的是一个具体的异常对象。 throws是用来声明方法内可能会有异常。
  2. throw写在方法内,throws写在方法的参数列表后面。

自定义异常

虽然系统已经提供了很多写好的异常类,但是由于项目不同,需求不同等,所以可能出现的异常也不同(可能你出现的异常,系统之前没有定义过这样的类)。为了解决这个问题,系统提供了自定义异常的语法。

如何自定义异常

创建一个类,继承于某个异常类即可。

自定义一个运行期异常:
public class ChooseOutOfBoundsException extends RuntimeException {

	private static final long serialVersionUID = 1L;

	public ChooseOutOfBoundsException(String message) {
		super(message);
	}

}

自定义异常的使用:

public class Test {
	
	public static void main(String[] args) {
		System.out.println("请输入您的选择(1-7):");
		int n = getChoose();
		System.out.println(n);
	}
	
	public static int getChoose() {
		Scanner sc = new Scanner(System.in);
		int choose = sc.nextInt();
		if(choose > 7 || choose < 1) {
			ChooseOutOfBoundsException e = new ChooseOutOfBoundsException("您选择的数字超出了范围[1,7]");
			throw e;
		}
		return choose;
	}
}
自定义一个非运行期异常
public class ChooseOutOfBoundsException2 extends Exception {
	private static final long serialVersionUID = 1L;

	public ChooseOutOfBoundsException2(String message) {
		super(message);
	}
	
}

使用非运行期异常

public class Test2 {

	public static void main(String[] args) {
		System.out.println("请输入1-7的数:");
		int n = 0;
		try {
			n = getChoose();
		} catch (ChooseOutOfBoundsException2 e) {
			System.out.println("你真调皮");
			//e.printStackTrace();
		}
		System.out.println(n);
	}
	
	public static int getChoose() throws ChooseOutOfBoundsException2 {
		Scanner sc = new Scanner(System.in);
		int choose = sc.nextInt();
		if(choose > 7 || choose < 1) {
			ChooseOutOfBoundsException2 e = new ChooseOutOfBoundsException2("选择超出范围[1,7]");
			throw e;
		}
		return choose;
	}

}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值