异常的捕获及处理

异常的捕获及处理

  • 认识异常
  • 处理异常
  • 多个异常的处理
  • 异常处理流程
  • throws关键字
  • throw关键字
  • 异常处理的模型(核心)
  • RuntimeException类
  • 断言:assert(了解)
  • 自定义异常类
  • 总结

异常的捕获及处理_第1张图片

认识异常

异常是导致程序中断执行的一种指令流,一旦产生异常没有正常处理的话,那么程序江湖中断执行。
范例:观察产生异常的代码

public class Hello{
	public static void main(String args[]){
		System.out.println("AAAAAA  计算开始  AAAAAA");
		System.out.println("BBBBBB  除法计算:"+(10/0)+"  BBBBBB");
		System.out.println("CCCCCC  计算结束  CCCCCC");
	}
}

在这里插入图片描述
出现异常,程序并未执行完,而是打印了一条信息。

处理异常

如果要在Java中进行异常的处理可以使用三个关键字的组合完成:try、catch、finally。有如下语法:
异常的捕获及处理_第2张图片
而此时给出的语法也有三种组合模式:try…catch、try…catch…finally、try…finally。
范例:实现异常的处理操作

public class Hello{
	public static void main(String args[]){
		System.out.println("AAAAAA  计算开始  AAAAAA");
		try{
			System.out.println("BBBBBB  除法计算:"+(10/0)+"  BBBBBB");
		}catch(ArithmeticException e){//e是一个对象
			System.out.println(e);
		}
		System.out.println("CCCCCC  计算结束  CCCCCC");
	}
}

在这里插入图片描述
此时程序出现异常仍可以正常执行完毕。
要想完整的输出异常信息,则可以使用printStackTrace()方法完成。

public class Hello{
	public static void main(String args[]){
		System.out.println("AAAAAA  计算开始  AAAAAA");
		try{
			System.out.println("BBBBBB  除法计算:"+(10/0)+"  BBBBBB");
		}catch(ArithmeticException e){//e是一个对象
			e.printStackTrace();
		}
		System.out.println("CCCCCC  计算结束  CCCCCC");
	}
}

在这里插入图片描述
范例:使用try…catch…finally来处理异常

public class Hello{
	public static void main(String args[]){
		System.out.println("AAAAAA  计算开始  AAAAAA");
		try{
			System.out.println("BBBBBB  除法计算:"+(10/0)+"  BBBBBB");
		}catch(ArithmeticException e){//e是一个对象
			e.printStackTrace();
		}finally{
			System.out.println("*************************");
		}
		System.out.println("CCCCCC  计算结束  CCCCCC");
	}
}

异常的捕获及处理_第3张图片
异常产生之后找到了相应的catch语句执行,而后处理异常完毕后继续执行finally的代码。

public class Hello{
	public static void main(String args[]){
		System.out.println("AAAAAA  计算开始  AAAAAA");
		try{
			System.out.println("BBBBBB  除法计算:"+(10/2)+"  BBBBBB");
		}catch(ArithmeticException e){//e是一个对象
			e.printStackTrace();
		}finally{
			System.out.println("*************************");
		}
		System.out.println("CCCCCC  计算结束  CCCCCC");
	}
}

在这里插入图片描述

多个异常的处理

在一个try语句之后可以编写多个catch进行处理,模拟一个输入的数字计算操作,假设要计算的数字使用过初始化参数设置的。
范例:修改程序代码

public class Hello{
	public static void main(String args[]){
		System.out.println("AAAAAA  计算开始  AAAAAA");
		try{
			int x = Integer.parseInt(args[0]);
			int y = Integer.parseInt(args[1]);
			int result=x/y;
			System.out.println("BBBBBB  除法计算:"+result+"  BBBBBB");
		}catch(ArithmeticException e){//e是一个对象
			e.printStackTrace();
		}finally{
			System.out.println("*************************");
		}
		System.out.println("CCCCCC  计算结束  CCCCCC");
	}
}

下面就有了这样几种执行情况:

  • 执行程序没有设置初始化参数:ArrayIndexOutOfBoundsException;
  • 执行程序的时候输入的内容不是数字:NumberFormatException;
  • 执行的时候被除数为0:ArithmeticException。
    只有在异常处理之后,异常之后的代码才能执行,finally代码永远会出现。
    为了保证程序出现错误之后仍然可以正常执行完,可以采用多个catch。
    范例:修改代码,处理多个异常
 public class Hello{
    	public static void main(String args[]){
    		System.out.println("AAAAAA  计算开始  AAAAAA");
    		try{
    			int x = Integer.parseInt(args[0]);
    			int y = Integer.parseInt(args[1]);
    			int result=x/y;
    			System.out.println("BBBBBB  除法计算:"+result+"  BBBBBB");
    		}catch(ArithmeticException e){//e是一个对象
    			e.printStackTrace();
    		}catch(NumberFormatException e){//e是一个对象
    			e.printStackTrace();
    		}catch(ArrayIndexOutOfBoundsException e){//e是一个对象
    			e.printStackTrace();
    		}finally{
    			System.out.println("*************************");
    		}
    		System.out.println("CCCCCC  计算结束  CCCCCC");
    	}
    }

异常处理流程

两个异常类的继承结构

java.lang.ArithmeticException java.lang.NumberFormatException
在这里插入图片描述 在这里插入图片描述

可以发现所有的异常类都是java.lang.Throwable的子类,此类定义如下:

public class Throwable extends Object implements Serializable

可以发现Throwable直接是Object子类。从JDK1.0开始提供。但是在Throwable下有两个子类,因此在开发中几乎不会考虑Throwable处理。
面试题:请解释Throwable下的Error和Exception子类的区别。

  • Error:在程序还未执行时出现的错误,一般指的是JVM出错,用户无法处理;
  • Exception:在程序运行中出现的异常,异常处理都是针对此类型完成的。
    因此,以后开发之中异常处理的最大父类就是Exception。
  1. 当程序出现异常时会由JVM自动的根据异常类型实例化一个指定的异常类对象;
  2. 程序需要判断当前的代码之中是否存在有异常处理逻辑,如果没有,则由JVM默认处理,处理方式输出异常信息,而后中断程序执行。
  3. 如果程序中存在异常处理,则try语句会捕获该异常类的实例化对象(想象为引用传递)
  4. 捕获到的异常类的实例化对象要与catch中的异常类型进行依次匹配;
  5. 如果catch匹配了异常,则用相应的代码进行处理,随后执行finally语句,如果没有任何catch匹配,则交由finally进行处理。
  6. 执行完finally代码之后要判断该异常是否已经处理过,若处理过,则执行后续代码,若没有,则交由JVM进行默认处理。
    异常的捕获及处理_第4张图片
    catch匹配跟参数传递类似,实例化对象有类型匹配,则进行接收,所有的异常都可以由Exception处理。
    如果try语句后有多个异常处理,则大的异常处理要放在小的异常处理之后,否则出错。
    范例:利用Exception处理异常。
     public class Hello{
        	public static void main(String args[]){
        		System.out.println("AAAAAA  计算开始  AAAAAA");
        		try{
        			int x = Integer.parseInt(args[0]);
        			int y = Integer.parseInt(args[1]);
        			int result=x/y;
        			System.out.println("BBBBBB  除法计算:"+result+"  BBBBBB");
        		}catch(Exception e){//e是一个对象
        			e.printStackTrace();
        		}finally{
        			System.out.println("*************************");
        		}
        		System.out.println("CCCCCC  计算结束  CCCCCC");
        	}
        }      

在实际开发中如果有明确要求,就分开处理。其他情况采用Exception是最方便的。

throws关键字

用户如何知道那些代码会产生怎样的异常?Java中提供throws关键字,其主要目的是明确告诉用户执行某一个方法有可能会产生哪些异常。所以throws主要是用于方法的声明处。
范例:观察throws关键字的使用

class MyMath{
	public static int div(int x,int y)throws Exception{
		return x/y;
	}
}

表示如果想执行本语句就必须进行异常处理。
范例:不处理异常直接调用

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

在这里插入图片描述
代码中出现throws声明,表示必须强制性进行异常处理操作。
范例:正常调用形式

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

但是使用了throws之后还有一个传递的问题,主方法也是一个方法,所以主方法也可以使用throws,那么就表示此时的主方法不进行异常的处理,而交给被调用处处理。

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

主方法之上就由JVM进行默认处理,一般主方法中应该把异常处理完成。

throw关键字

所有异常对象都是Java负责实例化,我们只能对异常进行捕获。Java中允许用户自己实例化异常对象,要抛出这个异常,就必须使用throw关键字。
范例:自己手工抛出异常

public class Hello{
	public static void main(String args[]) {//throws Exception
		throw new Exception("这是一个异常。");
	}
}

在这里插入图片描述
在这里插入图片描述
范例:异常处理

public class Hello{
	public static void main(String args[]) {//throws Exception
		try{
			throw new Exception("这是一个异常。");
		}catch(Exception e)	{
			e.printStackTrace();
		}
	}
}

在这里插入图片描述

异常处理的模型(核心)

设计除法计算方法,有如下要求:
在这里插入图片描述
范例:程序基本实现

class MyMath{
	public static int div(int x,int y)throws Exception{//交给被调用处处理
		int result=0;//保存计算结果
		System.out.println("************begin*************");
		result = x/y;
		System.out.println("*************end*************");
		return result;
	}
}
public class Hello{
	public static void main(String args[]) {//throws Exception
		try{
			System.out.println(MyMath.div(10, 2));
		}catch(Exception e)	{
			e.printStackTrace();
		}
	}
}

在这里插入图片描述
一旦程序出现错误,这个时候的运行结果如下。
在这里插入图片描述
范例:加入异常控制

    class MyMath{
	public static int div(int x,int y)throws Exception{//交给被调用处处理
		int result=0;//保存计算结果
		System.out.println("************begin*************");
		try{
			result = x/y;
		}catch(Exception e){
			throw e;//继续向上抛
		}finally{
			System.out.println("*************end*************");
		}
		return result;
	}
}
public class Hello{
	public static void main(String args[]) {//throws Exception
		try{
			System.out.println(MyMath.div(10, 0));
		}catch(Exception e)	{
			e.printStackTrace();
		}
	}
}

在这里插入图片描述
在以后的开发之中,一定会牵扯到资源的使用,例如文件、数据库操作前一定要打开,操作后一定要关闭。但是以上给出的异常处理模型可以简化:try…finally。

class MyMath{
	public static int div(int x,int y)throws Exception{//交给被调用处处理
		int result=0;//保存计算结果
		System.out.println("************begin*************");
		try{
			result = x/y;
		}finally{
			System.out.println("*************end*************");
		}
		return result;
	}
}
public class Hello{
	public static void main(String args[]) {//throws Exception
		try{
			System.out.println(MyMath.div(10, 0));
		}catch(Exception e)	{
			e.printStackTrace();
		}
	}
}

异常的捕获及处理_第5张图片

RuntimeException类

看段代码:

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

在这里插入图片描述
在这里插入图片描述
方法中出现throws就要进行异常处理,但此时并没有,观察NumberFormat类的继承结构。
在这里插入图片描述
因为NumberFormat类属于RuntimeException的子类,所以该异常属于选择性处理,即使不处理,编译的时候也不会出错,但是运行的时候会出错。
面试题:请解释Exception与RuntimeException的区别?列举出几个常见的RuntimeException。

  • RuntimeException是Exception的子类;
  • Exception定义的异常都需要强制性的处理,而RuntimeException的子类在编写代码时异常不需要强制性处理,由用户自己选择,如果不处理并且产生异常将交由JVM负责处理。
  • 常见的RuntimeException:ArithmeticException,NullPointerException、ClassCastException、NumberFormatException。

断言:assert(了解)

断言指的是在程序编写的过程之中,确定代码执行到某行之后数据一定是某个期待的内容。
范例:观察断言
异常的捕获及处理_第6张图片
断言默认情况不会启用,只有在程序运行时增加了配置参数才可以使用。
异常的捕获及处理_第7张图片
java -ea Hello
在这里插入图片描述

自定义异常类

Java异常类之中提供了大量类型,但是这些类型之中几乎都是与语法有关的异常,缺少业务有关类型,例如:输入某人成绩,如果超过100,那么就应该产生对应的异常,这些往往需要开发者自己定义,正因为如此才需要自定义异常类的概念。
异常类型主要有两个:Exception、RuntimeException。
范例:设计一个成绩异常
异常的捕获及处理_第8张图片
在这里插入图片描述

总结

在这里插入图片描述

你可能感兴趣的:(Java学习笔记)