异常处理总结

1.异常概述

1.1异常和错误

API中标准异常的顶级父类是Throwable类;
Throwable类有两个子类:Exception和Error;所有异常都是Exception类的直接或间接子类;所有错误都是Error的直接或间接子类;
异常(Exception):异常指的是程序运行时发生的不正常事件;异常能够被程序处理,保证程序继续运行下去;例如除数为0、文件没有找到、输入的数字格式不对
错误(Error):错误程序没法处理,例如内存泄漏。发生错误后,一般虚拟机会选择终止程序运行,程序员需要修改代码才能解决相关错误;
在这里插入图片描述

1.2 运行期异常和非运行期异常

Exception有很多子类;这些子类又可以分为两大类;
即运行时异常和非运行时异常;RuntimeException的子类都是运行时异常,其他的都是非运行时异常;
运行时异常:也称为非检测异常(unchecked Exception), 这些异常在编译期不检测,程序中可以选择处理,也可以不处理。如果不处理运行时会中断,但是编译没问题;
非运行时异常:也称为检测异常(checked Exception), 是必须进行处理的异常,如果不处理,将发生编译期错误;
在这里插入图片描述

在这里插入图片描述
下面我介绍几个常见的异常

1.1 常见异常

1.1.1 ArithmaticException 算术异常

当除数为0时会发生

	public static void main(String[] args) {
		int a=1,b=0;
		System.out.println(a/b);
	}

在这里插入图片描述

1.1.2 NullPointerException 空指针异常

当对一个空对象,即没有初始化,依然为null的对象调用属性或方法时
在这里插入图片描述

1.1.3 IndexOutOfBoundsException 索引越界异常

IndexOutOfBoundsException:索引越界异常,包括字符串索引StringIndexOutOfBoundsException和数组索引ArrayIndexOutOfBoundsException两种;
发生前提:当访问字符串中的字符或者数组中的元素,超过了其长度时;
在这里插入图片描述

1.1.4 NumberFormatException 数字格式异常

发生前提:当把一个字符串转换成数字时,字符串内容不是数字时发生;
在这里插入图片描述

1.1.4 ClassCastException 类型转换异常

发生前提:把父类对象转换成不相关的子类类型时;
在这里插入图片描述

2. 异常处理流程

2.1 try-catch语句

当我们有异常需要处理的时候,我们可以使用try-catch语句,将异常捕捉。如一下代码

public static void main(String[] args) {
 try{
     int x=100;
     int y=0;
     System.out.println("x/y="+x/y);
     System.out.println("x/y计算结束");
}catch(ArithmeticException e){
     System.out.println("发生了数学异常,注意除数不能为0.");
}
System.out.println("main方法运行结束");
}

运行结果
在这里插入图片描述
当系统捕捉到try语句块中的ArithmeticException,会在catch语句中查找相应的处理语句,然后执行。如果将ArithmeticException改为其他的异常(不包括它的父类异常),那么无法捕捉,就会抛出异常,不会执行最后的打印语句
注意:catch语句可以有多个,但是类型从子类到父类顺序,不能颠倒

2.2 finally语句

如果希望不管什么情况,有一些代码都必须被执行,那么就可以把这些代码写到finally块中;

	public static void main(String[] args) {
		try{
			int x=100;
			int y=0;
			System.out.println("x/y="+x/y);
			System.out.println("x/y计算结束");
		}catch(ArithmeticException e){
			System.out.println("发生了数学异常,注意除数不能为0.");
		}finally{
			System.out.println("finally代码块");
		}
		System.out.println("main方法运行结束");
	}

运行结果在这里插入图片描述
就算异常没有被处理,但是finally语句块依然会执行(包括return;还是会执行)
除了(System.exit(0))

3. 抛出异常

抛出异常时,我们需要通过throw和throws关键字

public class Calculator {
	public void div(int x,int y){
	//当除数为0时,抛出异常
	if(y==0){
		throw new Exception();//编译错误,需要使用throws关键字
	}
	System.out.println("x/y="+x/y);
}
}
//修改后
public class Calculator {
public void div(int x,int y) throws Exception{
	//当除数为0时,抛出异常
	if(y==0){
		throw new Exception();//编译错误,需要使用throws关键字
	}
		System.out.println("x/y="+x/y);
	}
}

一个方法如果使用了throws,那么调用该方法时,编译期会提醒必须处理这些异常,否则编译错误;
所以我们回到FileInputStream类的源码
在这里插入图片描述
我们可以发现它的源码代码中有throws FileNotFoundException 所以他就变为非运行期异常异常,需要处理。
一个方法如果使用了throws,那么调用该方法时,编译期会提醒必须处理这些异常,否则编译错误;

在这里插入图片描述

4. 自定义异常

4.1 自定义异常概述

抛出的异常不一定是使用系统定义好的,为了更好地来识别异常,我们也可以自己定义异常。
自定义异常类非常简单,只要继承API中任意一个标准异常类即可;
多数情况下,继承Exception类;也可以选择继承其他类型异常;
一般自定义异常类中不写其他方法,只重载必要的构造方法;

public class DataValueException extends Exception {
	public DataValueException() {
	}
	public DataValueException(String message) {
		super(message);
	}
	public DataValueException(Throwable cause) {
		super(cause);
	}
	public DataValueException(String message, Throwable cause) {
	}

4.1 自定义异常作业

题目:
模拟实现用户购买商品的功能,使用数组模拟商品列表,当购买的商品不存在或者商品库存为0时,抛出自定义异常。用户购买某一个商品时,对异常进行处理,并对库存进行改变。
考点:自定义异常、异常处理、throw/throws关键字


import java.util.Scanner;

public class ShopException {
	String[] goods_name={"苹果","西瓜","香蕉","梨","火龙果"};
	int[] num = {1,2,0,1,0};
	
	public void buy(int index) throws Exception{
		if(index>=num.length)
			throw new OutgoodException();
		if(num[index]==0)
			throw new NogoodException();
	}
	public void select(ShopException s){
		for(int i=0;i<s.num.length;i++){
			System.out.print(s.goods_name[i]+"\t");
		}
		System.out.println();
		for(int i=0;i<s.num.length;i++){
			System.out.print(s.num[i]+"\t");
		}
		System.out.println();
	}
	
	public void gobuy(ShopException s){
		Scanner in = new Scanner(System.in); 
		System.out.println("请选择你要购买的东西");
		int type=in.nextInt();
		try {
			s.buy(type);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		s.num[type]--;
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in = new Scanner(System.in);
		ShopException s = new ShopException();
		System.out.println("欢迎来到包子侠客的水果店!");
		System.out.println("1.查看店铺 2.购买水果 3.退出");
		int type = in.nextInt();
		while(type!=3){
			if(type==1)
				s.select(s);
			else if(type==2)
				s.gobuy(s);
			else if(type==3)
				break;
			else
				System.out.println("请输入正确的选项");
			System.out.println("1.查看店铺 2.购买水果 3.退出");
			type = in.nextInt();
			
		}
	}
}

5 断言

断言使用关键字assert表示,语法非常简单,

assert <布尔表达式> : <错误信息>
当布尔表达式的值是true时,忽略assert;
当布尔表达式的值是false时,发生AssertionError错误,程序中断;如果用第二种形式,同时显示错误信息;
Eclipse默认没有开启断言功能,要使用需要开启;
开启Eclipse中的断言功能;-
preferences->Installed JRES ->右边的edit
选择JRE 改变Default VM arguements
enableassertions 或者-ea

public class TestAssertion {
    private   static void test(int i){
		assert i!=1:"输入值不能为1";
		System.out.println("i="+i);
	}
	public static void main(String[] args) {
		test(2);
		test(1);
	}
}

在这里插入图片描述

import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; /** * 购物车类 */ public class Cart { //创建一个map对象,用来保存商品,key为商品,value为商品的数量 private Map<Goods, Integer> map = new HashMap<Goods, Integer>(); /** * 添加商品到购物车方法 * @param id 商品编号 * @param quantity 商品数量 */ public void addGoods(int id, int quantity){ Goods goods = GoodsDB.goodsMap.get(id); if(goods!=null){ Integer oQuantity = map.get(goods);//获取商品在购物车中原本的数量 if(oQuantity!=null){ oQuantity += quantity; }else{ oQuantity = quantity; } map.put(goods, oQuantity);//添加商品到map中 System.out.println("添加商品"+goods.getName()+"成功!"); }else{ System.out.println("添加失败!商品编号不存在!"); } } /** * 按指定的编号删除商品 * @param id 商品编号 */ public void delGoods(int id){ Goods goods = GoodsDB.goodsMap.get(id); if(goods!=null){ map.remove(goods);//从map删除商品 System.out.println("删除商品"+goods.getName()+"成功!"); }else{ System.out.println("删除失败!商品编号不存在!"); } } /** * 修改商品数量方法 * @param id 商品编号 * @param quantity 要修改的商品数量 */ public void updateGoods(int id, int quantity){ Goods goods = GoodsDB.goodsMap.get(id); if(goods!=null){ map.put(goods, quantity);//从map删除商品 }else{ System.out.println("修改失败!商品编号不存在!"); } } /** * 打印购物车商品列表 */ public void show(){ Set<Entry<Goods, Integer>> entrySet = map.entrySet(); System.out.println("编号\t单价\t数量\t名称\t总价"); for(Entry<Goods, Integer> entry:entrySet){ Goods goods = entry.getKey(); Integer quantity = entry.getValue(); System.out.println(goods.getId()+"\t"+goods.getPrice()+"\t"+quantity+"\t"+goods.getName()+"\t"+goods.getPrice()*quantity); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值