2022.0613学习Java笔记之异常的捕获及处理

异常指的是导致程序中断的一种指令流。

处理异常

如果在异常出现之后也希望程序可以正常执行完毕,那么在Java之中就可以采用如下代码结构来进行异常的处理操作。主要是用三个关键字:try、catch、finally。

try{
	//有可能出现异常的代码
}[catch(异常类型 对象){
	异常处理代码;
}catch(异常类型 对象){
	异常处理代码;
}...][finally{
	不管是否有异常都要执行
}]

如果程序出现异常之后,将直接跳转到catch之中进行处理处理完成之后,程序继续执行

在进行程序异常信息输出的时候,如果希望异常的信息完整,那么可以调用异常类之中的“printStackTrace()”方法进行详细输出。

范例:

public class TextDemo14{
	public static void main(String[] args) {
		System.out.println("1、出发计算开始");
		try{
			System.out.println("2、除法计算:" + (10/0));
			System.out.println("********");
		}catch(ArithmeticException e){
			e.printStackTrace();
		}finally{
			System.out.println("不管是否有异常都要执行");
		}
		System.out.println("3、除法计算结束");
	}
}

异常的处理流程

Java之中之所以会提供异常处理机制,主要目的就是为了减少用户的if...else判断 ,所以来讲以上的处理方案只是一种严格的方案。那么如果说现在某些代码分析起来比较麻烦,希望通过一些简单的方法进行异常处理的话,那么多个catch就不好用了,那么就要针对异常的流程做一个说明

首先看一下异常的继承结构

ArithmeticExceptionNumberFormatException
java lang Obiect
      |-java lang Throwable
        |-java lang Exception 
          I- java lang RuntimeException
            |- java lang ArithmeticExceptione
java lang Object e
    |- java.lang Throwable
      |- java.lang.Exception
        I- java lang RuntimeException
          |- jaya lang.Illegal ArgumentException

发现所有的异常都继承了Throwable类,而这个类指的就是抛出信息的操作类。在这个类之中发现有以下两个子类:

  • Error:表示JVM系统出错,此时系统还没有执行,所有用户不能处理;
  • Exception:表示的是所有程序运行过程之中出现的异常,用户可以进行处理;

那么一般而言,由于Throwable表示的范围太大了,那么程序之中处理的往往不会是Throwable,而都是Exception。按照之前的对象向上转型自动完成的概念来说,所有的子类对象都可以使用父类接收,那么就表示所产生出来的所有异常应该都是Exception的子类,所有的异常对象都应该可以自动转化为Exception

异常的处理流程图

 

通过以上的分析可以发现,所谓的异常的处理与catch匹配异常,那么就非常类似于方法的参数传递过程。唯一不同的是,此时的方法名称都统一使用了catch关键字表示,而所有的调用过程由try自动完成,那么既然是一个参数的传递过程,就可以按照之前所学习过的对象自动向上转型的方式进行处理,所有的异常类都是Exception的子类,那么所有的异常都可以使用Exception处理。

范例:

public class TextDemo14{
	public static void main(String[] args) {
		System.out.println("1、出发计算开始");
		try{
			int x = Integer.parseInt(args[0]);
			int y = Integer.parseInt(args[1]);
			System.out.println("2、除法计算:" + (x/y));
			System.out.println("********");
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			System.out.println("不管是否有异常都要执行");
		}
		System.out.println("3、除法计算结束");
	}
}

提示:在使用多个catch进行处理的时候,捕获范围小的异常一定要放在捕获范围大的异常以前,否则将出现编译错误。如果再要求不严格的情况下,那么就可以使用Exception处理所有的异常信息,这也是大部分系统常用的做法。

throws关键字

在类之中所有的操作都是以方法体现的,那么在方法的操作之中也是有可能出现异常的,如果说现在某些方法上出现异常之后希望被调用出进行处理的话,就是用throws进行声明。

范例:在方法定义上使用throws

class MyMath{
	public static int div(int x, int y) throws Exception {
		return x/y;
	}
}
public class TextDemo14{
	public static void main(String[] args) {
		try{
			System.out.println(MyMath.div(10,0));
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

 因为日后肯定会使用到大量的Java类库进行项目的开发,那么这些类库可能是你不熟悉的,但是在类方法设计的时候会考虑到用户执行此处可能出现的问题,一般都会在方法上使用throws 抛出异常,那么用户根据这些抛出就可以使用try...catch进行处理了。

同时需要注意的是,既然方法上可以使用throws,那么在主方法上也可以使用throws,表示主方法也不处理异常。那么就交给JVM进行处理

class MyMath{
	public static int div(int x, int y) throws Exception {
		return x/y;
	}
}
public class TextDemo14{
	public static void main(String[] args) throws Exception {
		System.out.println(MyMath.div(10,0));
	}
}

一般这样的代码很少出现,因为如果在调用出一定要处理异常

throw关键字

如果在异常处理过程中,使用了throw,那么就表示人为抛出一个异常对象。而throw一般都在代码块的结结构之中使用。

范例;手工抛出异常

public class TextDemo14{
	public static void main(String[] args) throws Exception {
		try{
			throw new Exception("自己抛着玩");
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

 区分throw与throws

  • throw主要用于方法体之中,表示人为的抛出一个异常类的实例化对象;
  • throws在方法的声明处使用表示此方法不处理异常,所有的异常交给被调用处进行处理

第五个代码模型:异常处理结构

那么到现在为止已经清楚了异常的基本处理形式,但是遗留的两个问题:finally无用、throw无用,那么为了更好解释这两个操作的含义,给出一个异常处理的标准结构。

范例:现在要求定义一个div()方法(定义在MyMath类里面),这个方法开发要求如下:

  • 此方法之中出现的异常一定要交给被调用处进行处理
  • 在进行除法计算开始首先要输出一行提示信息“1、除法计算开始,打开计算功能”;
  • 在出发计算完毕之后也要输出一行提示信息“2、除法计算结束,关闭计算功能”; 
class MyMath{
	public static int div(int x,int y) throws Exception {//异常由被调用出处理
		int result = 0;	//保存除法计算结果
		System.out.println("1、除法计算开始,打开计算功能。");
		try{
			result = x/y;	//进行除法计算
		}catch(Exception e){
			throw e;
		}finally{
			System.out.println("2、除法计算结束,关闭计算功能。");
		}
		return result;
	}
}
public class TextDemo14{
	public static void main(String[] args) throws Exception {
		try{
			System.out.println("除法计算结果:" + MyMath.div(10,0));
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

 

 在本结构之中就出现了try、catch、finally、throw、throws的标准组合应用,日后可以把两条输出语句理解为资源的打开和资源的关闭。当然,以上代码还可以更简化,直接使用try、finally操作

class MyMath{
	public static int div(int x,int y) throws Exception {//异常由被调用出处理
		int result = 0;	//保存除法计算结果
		System.out.println("1、除法计算开始,打开计算功能。");
		try{
			result = x/y;	//进行除法计算
		}finally{
			System.out.println("2、除法计算结束,关闭计算功能。");
		}
		return result;
	}
}

一般情况下当捕获了异常之后往往需要简单执行一些简单处理操作

RuntimeException类

下面观察一段代码

范例:将字符串变为int

public class TextDemo14{
	public static void main(String args[]){
		int num = Integer.parseInt("123");
		System.outprintln(num*num);
	}
}

 但是现在来观察一下在Integer类之中parseInt()方法的定义

public static int parseInt(Steing s) throws NumberFormatException

发现在parseInt9()方法定义的时候存在有throws关键字的抛出,按照之前所学,既然此此处存在有throws,那么在调用时就应该使用try...catch进行处理。可是此时没有强迫性的要求使用异常处理,观察NumberFormatException定义

NumberFormatException
java lang Object e
    |- java.lang Throwable
      |- java.lang.Exception
        I- java lang RuntimeException
          |- jaya lang.Illegal ArgumentException

可以发现NumberFormatException不仅仅是Exception的子类,它还继承了 RuntimeException,而在Java之中为了防变用户处理(并不是所有的异常都必须强制处理),那么RuntimeException的子类往往可以由用户选择性进行处理,如不需要也可以不处理。

区分Exception和RuntimeException的区别?请列举出几个你常见的 RuntimeException的子类

  • 用户可以处理的异常都要继承Exception类,而RuntimeException是Exception的子类;
  • Exception的异常要求用户强制性进行处理,而RuntimeException异常用户可以选择性进行处理,如果用户在编写代码过程之中没有处理,则出现异常后会由JVM进行默认处理。”
  • 常见的RuntimeException子类:ArithmeticException、ClassCastException、NullPointerException、DOMException。

自定义异常类

Java本身所提供的只是一个基础的异常处理操作支持,并且提供了一些比较常用的异常类型。但是在很多情况下有一些异常可能是不会提供的,如果想要对这些类异常进行处理,则必须定义属于自己的异常类。
那么要想定义属于自己的异常类,可以有两种选择:继承Exception或者是继承RuntimeException

范例:定义自己的异常

class EatDieException extends Exception{//定义异常类
	public EatDieException(String msg){
		super(msg);//调用父类构造
	}
}
public class TextDemo14{
	public static void main(String[] args) throws Exception {
		try{
			for(int x=1;x<=10;x++){
				System.out.println("小金子吃饭,已经吃了:" + x + "吨的米饭。");
				if(x>3){
					throw new EatDieException("小金子吃了三吨饭,快要撑死了。");
				}
			}
		}catch(Exception e){
			System.out.print("猪一般的饭量啊");
			e.printStackTrace();
		}
	}
}

 在正常使用情况下,很少会定义自己的异常类,

断言:assert

断言指的是在程序执行到某行语句的时候, 一定是预期的结果,当然,断言有可能是错误,也有可能是正确的。断言最早是在C++之中有所提供,后来到了JDK14之后才增加了此关键字。

public class TextDemo14{
	public static void main(String[] args) throws Exception {
		int x= 10;
		assert x ==100:"断言错误信息:x的内容不是100,而是" + x;
		System.out.println("x="+x);
	}
}

 默认情况下断言是不会启动的,如果要想使断言启动,则必须在执行的时候增加“-ea”参数

“java -ea TextDemo14”

Exception in thread "main" java.lang.AssertionError: 断言错误信息:x的内容不是100,而是10
        at TextDemo14.main(TextDemo14.java:4)

此时断言出现了错误,所以执行时会出现一个“AssertionError”。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值