复习17:异常Exception

异常

Exception是什么

  • 概念:程序中出现的各种异常的总称
  • 具体:Java中所有异常类的父类

Exception与Error的区别

  • Exception:不正常的事情,但是可以解决
  • Error:不可以解决,或者解决起来非常麻烦

Exception的分类

未检查异常(又叫运行时异常)
  • 父类:RuntimeException(RuntimeException的父类也是Exception)

  • 解释:编辑器未报错,程序运行时被抛出的异常。

  • 产生:由程序员马虎引起的异常,属于程序员意料之外的异常。例如空指针异常,数组越界异常。

  • 解决:该异常不要求程序员做相关预防措施,只需要更正代码即可

  • 示例:

    • NullPointerException
    • ArrayIndexOutOfBoundException
    • StringIndexOutOfBoundException
    • ClassCastException
    • EOFException
    • CurrentModifyException

程序遇到运行时异常时会立即结束,不会继续运行之后的代码

已检查异常
  • 父类:Exception

  • 解释:编辑器报错,编译不通过。

  • 产生:不是程序本身导致,有可能由外部因素引起。例如使用IO时发现指定文件不存在,则抛出FileNotFoundException

  • 解决:该异常程序员无法解决,但是可以预测并作出相应预防措施,当异常发生时启动预防措施

检查的执行者是编辑器,编辑器没检查出来的异常叫未检查异常,编辑器检查出来的异常叫已检查异常

处理已检查异常的方式

try-catch(-finally)

在出现异常的方法中,捕获并处理相关异常,可以处理未检查异常。

try-catch相当于if-else

  • try:正常情况下,执行try中的代码。try必须存在,且只能有一个。
  • catch:出现异常时,由catch抓取异常并执行相应catch中的代码。catch必须存在,且可以有多个。
  • finally:除了System.exit(0)之外的任何情况,finally中的代码都会执行,所以通常用来执行关闭流、JDBC链接等释放资源的操作。finally相当于try-catch的附加模块,可以省略;如果写了,那只能存在一个。

注意:catch按照从上往下的顺序进行抓取异常,有父子关系的异常应严格按照权限范围的从小到大排列(子类在上,父类在下),因为catch不会多次捕获同一个异常,即一旦某个异常被catch捕获过一次之后,下面的catch将不会继续捕获该异常;没有父子关系的异常则可以随意排序。

package day20191128;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Demo01 {
	public void T() {
		method();
	}
	public void method() {
        /**
        *try、catch、finally是三个独立的代码块,其中声明的变量都是局部变量,无法互通
        */
		try {
			FileInputStream f = new FileInputStream("a.txt");
		} catch (FileNotFoundException e) {
			/**
			 * FileNotFoundException e:创建异常的实例对象
			 * printStackTrace():打印错误信息
			 * catch中的内容可自定义
			 */
            System.out.println("发生错误!");
			e.printStackTrace();
		}catch(IOException e){
            /**
            *IOEception是FileNotFoundException的父类,所以需要放在下面
            */
            e.printStackTrace();
        }catch(..){
            
        }finally{
            
        }
		/**
		 * try-catch之后的代码会正常运行
		 */
		System.out.println(1);
	}
}

注意:异常点之后的代码不会被执行;try-catch之后的代码会正常运行

throws

在除主方法外的方法声明上抛出方法,方法调用者处理被抛出异常(也可以选择继续向外抛出,但是最后一级调用者必须处理异常)。注意:throws可以同时抛出多个异常,用逗号分隔。

package day20191128;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Demo02 {
	public static void main(String[] args) {
		Test t = new Test();
		try {
			t.method();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		
	}
}
class Test{
	public void method() throws FileNotFoundException {
		FileInputStream f = new FileInputStream("a.txt");
	}
}

注意:throws之后的语句不会执行

throw

throw也是抛出异常的一种方式,与throws有以下区别

  • throws通常是编辑器强制要求抛出(异常必须存在),throw是程序员人为地制造一个异常并抛出

  • throws在方法声明中抛出异常,抛给方法调用者;throw在方法体内执行,抛给方法本身

  • throws抛出的是异常的名称,throw抛出的是异常的实例对象

  • throws可以同时抛出多个异常,throw只能抛出一个

  • throws抛出的异常可能会发生也可能不会发生,throw的语句被执行说明异常必定发生

方法调用者也要处理被throw抛出的异常

  1. 抛出
package day20191128;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Demo02 {
	public static void main(String[] args) {
		Test t = new Test();
		try {
			t.method();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
class Test{
	public void method() throws FileNotFoundException {
		throw new java.io.FileNotFoundException("文件未找到");
	}
}

  1. 方法内处理
package day20191128;


public class Demo02 {
	public static void main(String[] args) {
		Test t = new Test();
		t.method();
	}
}
class Test{
	public void method()  {
		try {
			throw new java.io.FileNotFoundException("文件未找到");
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}

注意:throw之后的语句同样无法执行

关于finally的小扩展

代码如下,问最终输出结果是什么?

package day20191128;

public class Demo03 {
	public static void main(String[] args) {
		Test t = new Test();
		System.out.println(t.method());
		System.out.println(t.a);
	}
}
class Test{
	int a = 18;
	public int method()  {
		try {
			int i = a/0;
			return a;
		}catch(Exception e) {
			return a;
		}finally {
			a++;
		}
	}
}

答:以上代码的最终输出结果为18,19。

分析:从答案中我们可以看出finally在catch的return之后执行,众所周知,return的作用是返回结果并结束方法,然而结果却与我们的认知相悖,这是为什么呢?这是由return的执行过程决定的,return的执行分为两部分:

  1. 第一次执行到return:将结果保存到缓冲区,不直接返回
  2. 监测到所有代码执行完毕:将缓冲区中的结果返回,结束方法

finally的执行是在return的第一步之后、第二步之前,因为return是返回缓冲区中的结果,所以a++影响不到方法返回值,最终得到了18,19的结果。


自定义异常

package day20191128;

/**
 * 
 * @author DL
 * 用户名或密码错误异常
 * 已检查异常:extends Exception
 * 未检查异常:extends RuntimeException
 */
public class IdOrPwdException extends Exception{

	public IdOrPwdException() {
		super("用户名/密码错误");
		// TODO Auto-generated constructor stub
	}

	public IdOrPwdException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
		// TODO Auto-generated constructor stub
	}

	public IdOrPwdException(String message, Throwable cause) {
		super(message, cause);
		// TODO Auto-generated constructor stub
	}

	public IdOrPwdException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}

	public IdOrPwdException(Throwable cause) {
		super(cause);
		// TODO Auto-generated constructor stub
	}
	 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章