Java异常

1、引入异常并进行简单处理

问题1:异常是什么?
异常:程序在运行过程中出现了可逆转或不可逆转的错误现象,异常处理已经成为衡量一门语言是否成熟的标准之一,目前的主流编程语言如:C、C++、C#、Ruby、python、Java等都提供了异常处理机制。
异常处理的目的:为了提高系统的健壮性、稳定性,良好的系统的设计应该有完整的异常处理。因为如果不处理异常,异常会直接交给JVM,jvm会报错,并将结束程序。

1.1、示例引出异常

/**

  • 功能:输入被除数和除数,求商并输出

  • 技能:引入异常

  • Java提供了异常处理机制,一旦出现异常,Java会捕获并继续处理

  • 问题1:一旦出现异常,后续的语句不执行

  • 问题2:Java系统提供的异常提示信息过于专业,不友好

  • 解决:

  • 方案1:通过if-else进行判断,如果输入的是非数字,如果输出是0,给出提示信息

    • 不可行!!
      1、代码臃肿
      2、程序员要花很大精力"堵漏洞“
      3、程序员很难堵住所有“漏洞”
  • 方案2:在Java提供的异常处理机制的基础上,进行简单的捕获和处理即可

  •     try--catch-finally 
    
  •     throws  throw
    

*/

/**

  • 尝试通过if-else来解决异常问题。
  • 不可行!!
    1、代码臃肿
    2、程序员要花很大精力"堵漏洞“
    3、程序员很难堵住所有“漏洞”
    */
public class Test2 {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		System.out.print("请输入被除数:");
		int num1 = 0;
		if (in.hasNextInt()) { // 如果输入的被除数是整数
			num1 = in.nextInt();
		} else { // 如果输入的被除数不是整数
			System.err.println("输入的被除数不是整数,程序退出。");
			System.exit(1); // 结束程序执行
		}
		System.out.print("请输入除数:");
		int num2 = 0;
		if (in.hasNextInt()) { // 如果输入的除数是整数
			num2 = in.nextInt();
			if (0 == num2) { // 如果输入的除数是0
				System.err.println("输入的除数是0,程序退出。");
				System.exit(1);
			}
		} else { // 如果输入的除数不是整数
			System.err.println("输入的除数不是整数,程序退出。");
			System.exit(1);
		}
		System.out.println(String.format("%d / %d = %d", 
				num1, num2, num1/ num2));
		System.out.println("感谢使用本程序!");
		System.out.println("程序运行结束");
	}
}

1.2、使用try-catch进行异常处理

问题2:如何解决异常
使用:try-catch
/**
功能:输入被除数和除数,求商并输出
技能:使用try-catch进行异常处理
总结:
1.什么是异常(Exception)
异常( Exception 也称例外)就是在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序

2.try-catch进行异常处理的执行过程

 情况1:try块中代码没有出现异常
不执行catch块代码,执行catch块后边的代码

情况2:try块中代码出现异常,catch中异常类型匹配(相同或者父类)
try块中后续语句不执行-----执行catch块代码-----执行catch块后边的代码

情况3:try块中代码出现异常, catch中异常类型不匹配
try块中后续语句不执行-----不执行catch块代码------------不执行catch块后边的代码,程序会中断运行

3.catch块中如何处理异常

	输出用户自定义异常信息
	System.err.println("除数不能为零。");
	System.err.println("被除数和除数必须是整数。");
	
	调用异常对象的方法输出异常信息
	toString ( )方法,显示异常的类名和产生异常的原因
	void printStackTrace()   输出异常的堆栈信息
	String getMessage()返回异常信息描述字符串,是printStackTrace()输出信息的一部分
	
	继续向上抛出异常
	throw e

4.强调

  • 1.出现异常后,Java会生成相应的异常对象,Java系统,寻找匹配的catch块,找到后将异常对象付给catch块异常参数
  • 2.出现异常后,try块中尚未执行的语句不会执行
  • 3.出现异常后并处理后,catch块后面的语句还会执行
    */
public class Test3 {
	public static void main(String[] args) {
		Scanner  input  = new Scanner(System.in);
		try{
			//输入被除数
			System.out.println("请输入被除数");
			int num1 = input.nextInt();//InputMismatchException
			//输入除数
			System.out.println("请输入除数");
			int num2 = input.nextInt();
			
			//求商输出结果
			System.out.println(num1+"/"+num2+"="+num1/num2);
		}catch(Exception e){
			//1.用户自定义信息
			//System.out.println("被除数和除数必须是数字,除数不能是0");	
			//2.使用java提供的异常信息
			//System.out.println(e.toString());
			//System.out.println(e.getMessage());
			//e.printStackTrace();
			//3.继续向上抛出异常(catch后续代码不执行)
			throw e;
		}		
		//谢谢使用
		System.out.println("谢谢你的使用");
		System.out.println("程序结束");
	}
}

2、使用try-catch-finally处理异常

功能:输入被除数和除数,求商并输出
技能:使用try-catch-finally进行异常处理

问题1:在什么情况,System.out.println(“谢谢你的使用”);System.out.println(“程序结束”);不执行

  • 情况1:catch块中有throw语句
  • 情况2:没有匹配的catch块语句 InputMismatchException / ArithmeticException
  • 情况3:遇到return语句

问题2:即使出现如上三种情况,希望某些语句也必须执行
解决:finally语句

问题3:哪些语句可以放到finally语句中

  • 关闭数据库连接 conn.close();
  • 关闭IO流 fis.close()
  • 关闭socket连接 socket.close()

问题4:是不是所有情况下finally语句都执行

  • 唯一例外
  • System.exit(0):退出JVM 程序结束
  • 0:正常终止 / 非 0 的状态码表示异常终止
  • return:结束当前方法
    示例:
public class Test4 {
	public static void main(String[] args) {
		Scanner  input  = new Scanner(System.in);
		try{
			//输入被除数
			System.out.println("请输入被除数");
			int num1 = input.nextInt();//InputMismatchException
			//输入除数
			System.out.println("请输入除数");
			int num2 = input.nextInt();
			//求商输出结果
			System.out.println(num1+"/"+num2+"="+num1/num2);
			System.exit(0);
			//return;
		}catch(Exception e){
			//1.用户自定义信息
			System.err.println("被除数和除数必须是数字,除数不能是0");	
			//2.使用java提供的异常信息
			System.err.println(e.toString());
			//System.out.println(e.getMessage());
			//e.printStackTrace();
			//3.继续向上抛出异常(catch后续代码不执行)
			//throw e;
			return;
		}finally{
			//谢谢使用
			System.out.println("谢谢你的使用");
		}
		System.out.println("程序结束");
	}
}

3、多重catch和异常分类

3.1、多重catch
问题:System.err.println(“被除数和除数必须是数字,除数不能是0”);
* 不完全准确,到底是哪种错误
解决:多重catch
ArithmeticException
InputMismatchException
技能:使用多重catch进行精确的异常处理

注意:
1.依次和各个catch块进行比较,如果匹配,执行该catch块的代码,后续catch块不会比较和执行
2.各个catch块的顺序:先子类后父类

3.多个catch最多执行一个.

Error

Exception
-RuntimeException
-Checked Exception

示例
/**

  • 功能:输入被除数和除数,求商并输出
  • 技能:使用多重catch进行异常处理
    问题:System.err.println(“被除数和除数必须是数字,除数不能是0”);
    *不完全准确,到底是哪种错误
    *解决:多重catch *
    注意:
  • 1.依次和各个catch块进行比较,如果匹配,执行该catch块的代码,后续catch块不会比较和执行
  • 2.各个catch块的顺序:先子类后父类
  • 3.多个catch最多执行一个
    */
public class Test5 {
	public static void main(String[] args) {
		Scanner  input  = new Scanner(System.in);
		try{
			//输入被除数
			System.out.println("请输入被除数");
			int num1 = input.nextInt();//InputMismatchException
			//输入除数
			System.out.println("请输入除数");
			int num2 = input.nextInt();
			//求商输出结果
			System.out.println(num1+"/"+num2+"="+num1/num2);
			System.exit(0);
			//return;
		}catch(ArithmeticException e){			
			System.err.println("除数不能是0");	
		}catch(InputMismatchException e){			
			System.err.println("被除数和除数必须是数字");	
		}catch(Exception e){			
			System.err.println("其他异常");	
			e.printStackTrace();
		}finally{
			//谢谢使用
			System.out.println("谢谢你的使用");
		}
		System.out.println("程序结束");
	}
}

3.2、异常分类

示例
/**

  • 异常的分类
  • 1.运行时异常(RuntimeException)
  • 用户可以处理也可以不处理
  • 2.检查异常(Checked Exception)编译时异常
  • 用户必须进行异常处理,否则编译出错
  • 怎么处理
  • 1.try-catch-finally
  • 2.throws
    */
public class Test6 {
	public static void main(String[] args) throws IOException {
		 //1
//		String str = null;
//		System.out.println(str.toLowerCase());		
		//2
		Scanner  input  = new Scanner(System.in);
		//输入被除数
		System.out.println("请输入被除数");
		int num1 = input.nextInt();
		
		 //3
		try {
			Class.forName("com.bjsxt.exception.test.Test1").newInstance();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		
		//4
		InputStream is = new FileInputStream("c:/abc.txt");
		is.close();
	}
}

异常分类总结
在这里插入图片描述
Throwable 类
– Error

–Exception

  1. 运行时异常 Runtime Exception(unchecked Exception)
  •   RuntimeException
    
  •      -- ArithmeticException
    
  •      -- InputMismatchException
    
  •      -- NullPointerException
    
  •      -- ArrayIndexOutOfBoundsException
    
  •     可以不要处理 
    

2.检查异常(Checked Exception) 编译时异常
检查时异常 Checked Exception 编译时的异常
–SQLException
–ClassNotFoundException
–FileNotFoundException
–IOException
我们必须处理
例如:
Class.forName(“com.sxt.exception.Test”);
Class.forName(“com.sxt.exception.Test”).newInstance();

InputStream is = new FileInputStream(“e:/abc.txt”);
is.close();

用户必须进行异常处理,否则编译出错
怎么处理?
1.try-catch-finally
2.throw/throws

总结:
Java编译器要求Java程序必须捕捉处理或声明抛出所有的 检查时异常(Exception)。
但对 运行时异常(RuntimeException) 可以不作处理。

注意:只有Java提供了Checked检查时异常,体现了Java的严谨性,提高了Java的健壮性。同时也是一个备受争议的问题。
在这里插入图片描述
在这里插入图片描述
4、throw 异常_除数不能是负数
throw 和 throws
/**

  • 功能:给出被除数和除数,求商并输出;如果除数是负数,也抛出异常
  • 技能:throws throw
    */
public class Test7 {
	public static void main(String[] args) throws Exception {
//		try {
//			devide();
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		devide();
	}
	public static void devide() throws Exception{
		Scanner  input  = new Scanner(System.in);
		//输入被除数
		System.out.println("请输入被除数");
		int num1 = input.nextInt();
		//输入除数
		System.out.println("请输入除数");
		int num2 = input.nextInt();
		//如果除数是负数,也抛出异常
		if(num2<0){
			//throw new RuntimeException("除数不能是负数");	运行异常		
			throw new Exception("除数不能是负数");	检查异常 必须处理		
		}
		//求商输出结果
		System.out.println(num1+"/"+num2+"="+num1/num2);
		//谢谢使用
		System.out.println("谢谢你的使用");
		System.out.println("程序结束");
	}
}

总结:

throw和throws的区别
1.位置不同 throw位于方法体中,throws位于方法声明中
2.内容不同 throw 后面跟一个异常对象,throws后面跟一个或多个异常类
3.作用不同 throw 此处有异常,我负责抛出,这里是异常的源头;
throws:该方法中有异常,但是没有进行try-catch,我负责声明,告诉调用者

5、throw异常案例
throws throw 案例之性别只能是男女
功能:Person类的性别只能是男或者女,否则抛出异常
Person类的年龄只能在1—130直接,否则抛出异常
//throw new RuntimeException(“性别只能取值男或者女”);
throw new Exception(“性别只能取值男或者女”); //检查异常
检查异常的处理:要么抛出,要么处理

public class Person {
	private String name;
	private String sex;
	private int age;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) throws Exception{
		if("男".equals(sex)|| "女".equals(sex)){
			this.sex = sex;
		}else{
			//this.sex = "男";
			//throw new RuntimeException("性别只能取值男或者女");
			throw new Exception("性别只能取值男或者女");
		}
		
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", sex=" + sex + ", age=" + age + "]";
	}
}

/**

  • 功能:Person类的性别只能是男或者女,否则抛出异常
  • Person类的年龄只能在1---130直接,否则抛出异常
    

*/

public class Test8 {
	public static void main(String[] args) {
		Person p = new Person();
		p.setName("xiaohong");
		try {
			p.setSex("123");
			p.setAge(200);
			System.out.println(p);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		//Class.forName("");
	}
}

6、自定义异常
为了让异常信息更 直观、人性化,可以采用 自定义异常

(1) SexException extends RuntimeException 性别异常
(2) DevideByMinusException extends Exception 为负数异常

自定义异常

  • 1.继承Exception或者RuntimeException
  • 2.重写父类的两个构造方法:无参数构造方法和输入message的有参数构造方法
  • 3.自定义异常可以有额外的成员变量,具体值可以通过构造方法传入,此时一般要重写toString()

示例1:继承RuntimeException
/**

  • 自定义异常
  • 1.继承Exception或者RuntimeException
  • 2.重写父类的两个构造方法:无参数构造方法和输入message的构造方法
  • 3.自定义异常可以有额外的成员变量,具体值可以通过构造方法传入,此时一般要重写toString()
    */
public class SexException extends RuntimeException{
	public SexException() {
		super();
	}
	public SexException(String message) {
		super(message);
	}
}
public class Person {
	private String name;
	private String sex;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		if("男".equals(sex)|| "女".equals(sex)){
			this.sex = sex;
		}else{
			//this.sex = "男";
			//throw new RuntimeException("性别只能取值男或者女");
			throw new SexException("性别只能取值男或者女");
		}
		
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", sex=" + sex + ", age=" + age + "]";
	}
}

/**

  • 功能:Person类的性别只能是男或者女,否则抛出异常
  • Person类的年龄只能在1---130直接,否则抛出异常
    

*/

public class Test8 {
	public static void main(String[] args) {
		Person p = new Person();
		p.setName("xiaohong");
		try {
			p.setSex("123");
			p.setAge(200);
			System.out.println(p);
		} catch (SexException e) {
			e.printStackTrace();
		}
		//Class.forName("");
	}
}

注意:由于SexException是运行时异常,所以try{}catch{}可以不写。

示例2:继承Exception

public class DevideByMinusException extends Exception{
	private int minus;
	public DevideByMinusException() {
		super();
	}

	public DevideByMinusException(String message) {
		super(message);
	}
	
	public DevideByMinusException(String message, int minus) {
		super(message);
		this.minus = minus;
	}

	@Override
	public String toString() {
		return super.toString()+"("+minus+")";
	}
}

/**

  • 功能:给出被除数和除数,求商并输出;如果除数是负数,也抛出异常
    */
public class Test7 {
	public static void main(String[] args){
//		try {
//			devide();
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		try {
			devide();
		} catch (DevideByMinusException e) {
			System.out.println(e.toString());
			//e.printStackTrace();
		}
	}
	
	public static void devide() throws DevideByMinusException {
		Scanner  input  = new Scanner(System.in);
		//输入被除数
		System.out.println("请输入被除数");
		int num1 = input.nextInt();
		//输入除数
		System.out.println("请输入除数");
		int num2 = input.nextInt();
		//如果除数是负数,也抛出异常
		if(num2<0){
			//throw new RuntimeException("除数不能是负数");			
			throw new DevideByMinusException("除数不能是负数",num2);			
		}
		
		//求商输出结果
		System.out.println(num1+"/"+num2+"="+num1/num2);
		
		//谢谢使用
		System.out.println("谢谢你的使用");
		System.out.println("程序结束");
	}
}

4、异常链及案例

  • //对底层异常进行处理(给程序员)
    System.out.println(“程序员看到的异常信息:”+e);
    //抛出一个更友好的异常(给用户)
    throw new AuctionException(“竞拍价格必须是数字”);

标准javaBean – java实体类
标准java Bean的基本条件:
(1)必须提供私有的成员变量。
(2)必须为私有的成员变量提供公有的set/get方法。
(3)必须有无参的构造方法。
示例
/**
*功能:用户输入拍卖价格,系统将拍卖价格保存到数据库中,给出提示信息
*技能:异常转译/异常链 分层结构
*Auction拍卖 bid 竞价
*1.分层结构
*用户
*表示层(视图层)
*业务层Service
*数据访问层DAO
*数据库

  • 下一层为上一层提供服务,上一层直接调用下层提供的服务即可
  • 2.异常转译
  • //对底层异常进行处理(给程序员)
    System.out.println(“程序员看到的异常信息:”+e);
    //抛出一个更友好的异常(给用户)
    throw new AuctionException(“竞拍价格必须是数字”);
    */
public class Client {
	public static void main(String[] args) {
		//输入价格
		//String sprice ="123";
		String sprice ="123abc";
		//完成业务
		AuctionService as = new AuctionService();
		try {
			as.bid(sprice);
		} catch (AuctionException e) {
		  //System.out.println("客户看到的异常信息:"+e.getMessage());
			System.out.println("客户看到的异常信息:"+e);
		}
	}
}

/**

  • 数据访问层,访问数据库
    */
public class AuctionDao {
	//保存竞价到数据库中
	public void savePrice(String sprice){
		//转换成数字
		int price = Integer.parseInt(sprice);//"123"---123  "abc"---???
		//保存到数据库中
		System.out.println("将价格保存到数据库中:"+price);
	}
}

/**

  • 业务层
    */
public class AuctionService {
	//完成竞价业务
	public void bid(String sprice) throws AuctionException{
		AuctionDao ad = new AuctionDao();
		try{
			ad.savePrice(sprice);	
		}catch(NumberFormatException e){
			//对底层异常进行处理(给程序员)
			System.out.println("程序员看到的异常信息:"+e);
			//抛出一个更友好的业务异常(给用户)
			throw new AuctionException("竞拍价格必须是数字");
		}
			
	}
}

/**

  • 拍卖异常
    */
public class AuctionException  extends Exception{

	public AuctionException() {
		super();
	}

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

总结

1、运行时异常和Checked异常有什么区别?
简单来说运行时异常可以不处理,编译时异常必须要处理

2、多重catch块的执行顺序?
子类先执行

3、throw和throws关键字有什么区别?
throws出现在方法函数头;而throw出现在函数体。
throws表示出现异常的一种可能性,并不一定会发生这些异常;
throw则是抛出了异常,执行throw则一定抛出了某种异常对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jsxllht

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值