07_异常处理

风格不统一 提交于 2019-12-18 20:33:30

一、异常的分类:

大的方面:Error 、 Exception
1.Error: 这种错误 我们一般不处理

public static void main(String[] args) {
		int[] arr = new int[1000000000];
	}

在这里插入图片描述
(内存溢出错误)

2.Exception :才是我们处理的重点:

编译期异常:在编译期间发生的异常(checked Exception)
运行时异常:在编译期无法知道  直到程序运行时才发生的异常 称为运行时异常(unchecked  Exception)

在这里插入图片描述
1.运行时异常
是指编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序 员应该积极避免其出现的异常。java.lang.RuntimeException类及它的子 类都是运行时异常。
对于这类异常,可以不作处理,因为这类异常很普遍,若全处理可能会对 程序的可读性和运行效率产生影响。
2.编译时异常
是指编译器要求必须处置的异常。即程序在运行时由于外界因素造成的一 般性异常。编译器要求Java程序必须捕获或声明所有编译时异常。
对于这类异常,如果程序不处理,可能会带来意想不到的结果。

二、常见异常:

throwable 两个直接子类 :error 、exception
在这里插入图片描述
在这里插入图片描述

java.lang.RuntimeException
    ClassCastException 
    ArrayIndexOutOfBoundsException
    NullPointerException 
    ArithmeticException 
    NumberFormatException 
    InputMismatchException
java.io.IOExeption 
     FileNotFoundException
     EOFException
java.lang.ClassNotFoundException 
java.lang.InterruptedException 
java.io.FileNotFoundException 
java.sql.SQLException

1.运行时异常:

ArrayIndexOutOfBoundsException(数组下角标越界异常)

public static void main(String[] args) {
		int[] arr = new int[5];
		for(int i = 0 ; i < 10;i++) {
			System.out.println(arr[i]);
		}
	}

在这里插入图片描述

NullPointerException(空指针异常)
在这里插入图片描述
在这里插入图片描述

ArithmeticException(算数异常)

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

在这里插入图片描述
ClassCastException(类型转换异常)

public static void main(String[] args) {
		Object obj = new SalariedEmployee();
		HourlyEmployee he = (HourlyEmployee)obj;
	}

在这里插入图片描述
InputMismatchException(输入类型匹配异常)

public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int i = sc.nextInt();
	}

在这里插入图片描述

2.编译期异常:

ParseException(解析异常)

public static void main(String[] args) {
		Date date = new Date();//获取系统当前时间
		System.out.println(date);
		//对时间进行格式化 将一个Date时间格式化为一个字符串时间
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		String strDate = sdf.format(date);
		System.out.println(strDate);
		//也可以将一个字符串类型时间解析为Date
		String dateStr = "2019-11-11";
		Date d =null;
		try {
			d = sdf.parse(dateStr);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(d);
	}

在这里插入图片描述

编译期异常和运行时异常的一个区别:

编译期异常必须处理 不处理程序无法运行 处理的重点
运行时异常 可以不处理 但是在运行期间有可能发生异常
但是针对运行时异常 往往可以通过完善代码逻辑来进行避免异常的发生

例如:(运行时异常可以加判断来避免异常)
在这里插入图片描述
在这里插入图片描述

三、异常的处理机制:

异常对于程序的影响:
1 编译期异常:程序直接导致不能运行
2 运行时异常:将导致程序运行到异常发生处 

程序将直接终止运行 而且后续代码都将不再执行。

异常的处理:
方式一:try-catch-finally
方式二:throws + 异常类型

Java中异常的处理模型:抓抛模型

1、try-catch-finally(抓)

try {

有可能发生异常的代码。

}catch(需要捕获的异常的类型  变量){

当发生匹配的异常时候才会执行的代码。
针对捕获到的异常的处理。

}finally{//可选块

无论代码是否发生异常 都需要执行的代码

}

异常中常用的方法:

1.public void printStackTrace()
在这里插入图片描述
在这里插入图片描述

将此throwable和其追溯打印到标准错误流。 此方法在错误输出流上为该Throwable对象打印一个堆栈跟踪,
该值为字段System.err的值。 第一行输出包含该对象的toString()方法的结果。
剩余行表示先前通过方法fillInStackTrace()记录的数据。 
该信息的格式取决于实现,但以下示例可能被认为是典型的:
public class ExceptionDemo {
	public static void main(String[] args) {
	Scanner sc = new Scanner(System.in);
	int i =0;
	try{ i = sc.nextInt();
	}
	catch (InputMismatchException e) {
		e.printStackTrace();
		System.out.println("发生输入类型不匹配异常 请输入int类型");
}
	}
}

在这里插入图片描述

2.public String getMessage()

返回此throwable的详细消息字符串。(可能是null)

在这里插入图片描述
在这里插入图片描述

public class ExceptionDemo {
	public static void main(String[] args) {
	Scanner sc = new Scanner(System.in);
	int i =0;
	try{ i = sc.nextInt();
	}
	catch (InputMismatchException e) {
		System.out.println(e.getMessage());
		System.out.println("发生输入类型不匹配异常 请输入int类型");
}
	}
}

在这里插入图片描述

注意:

1.在try。。。catch 可以有多个catch块 将来代码发生那个异常 就执行那个catch的代码

public class ExceptionDemo {
	public static void main(String[] args) {
		int[] arr = new int[]{ 2 , 5, 6, 0 ,7 ,9};
		int sum = 0;
		try {
			for (int i = 0 ;i < 10 ; i++) {
				if(i == 2 ) {
					arr = null;
				}
				sum += arr[i];
				System.out.println(sum/arr[i]);
			}
	
		} catch (ArithmeticException e) {
			System.out.println("发生了算数异常 "+e.getMessage());
		}catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("发生了数组下标越界异常 " + e.getMessage());
		}catch (NullPointerException e) {
			System.out.println("发生了空指针异常 " + e.getMessage());
		}catch (Exception e) {
			System.out.println("发生未知异常 " + e.getMessage() );
		}
		
	}
}

在这里插入图片描述

2.在catch捕获异常时 首先匹配最精确的异常类型 如果没有具体精确的类型匹配 才匹配父类异常
3.针对多异常的catch 顺序是否有要求:

1 对于Exception的catch 必须位于所有catch的最后
2 同级别的异常  顺序无所谓
3 遵循一个原则  从小到大

4.jdk7及之后的版本 多异常的新写法:

 catch (ArithmeticException | ArrayIndexOutOfBoundsException | NullPointerException e) {
			e.printStackTrace();
			System.out.println(e.getMessage());
		}

在这里插入图片描述

在上述写法中 不能出现大范围的异常类型(上述写法中 不能出现Exception) 只能时同级别异常类型

5.finally代码块:

finally {
			System.out.println("finally 代码块执行....");
		}

finally 无论try中的代码是否发生异常都将要执行的代码
(一般用在数据库链接的释放 、 对于文件操作流的关闭等)

6.try-catch-finally三种写法:(try必须有、catch finally可以没有,但是不能全没有)

try。。。catch
try 。。。finally
try 。。。 catch  。。。 finally

上述内容概述:

异常处理
Error  
Exception 
Exception-- 编译期异常/受检异常(checked Exception) 必须处理 
RuntimeException-- 运行时异常 /非受检异常(Unchecked Exception)
面试题:列举5个常见的运行时异常:
数组下标越界、空指针、类型转换、算数异输入类型匹配异常
处理方式:
1 默认处理(由jvm处理):在控制台输出异常信息 终止程序执行
2 try 。。。 catch。。。finally
获取异常信息的方式:Exception/子类  变量
两个方法:1.void  printStacktrace();
2.String getMessage();
注意:try  catch  finally  return(面试中的题)

final  finally区别

2.throws(抛)

public static Date str2Date(String strDate) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		//将获取的字符串的时间 转换为Date
		Date d = sdf.parse(strDate);
		return d;
	}

try 和throws
throws抛出的异常的类型
throws可以抛出多种异常类型

声明抛出异常是Java中处理异常的第二种方式 :
如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这 种异常,
则此方法应显式地声明抛出异常,表明该方法将不对这些异常进行处理, 而由该方法的调用者负责处理。 
在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可 以是方法中产生的异常类型,
也可以是它的父类。

在方法重写中 子类重写父类的方法时 不能抛出比父类更大范围的异常类型 子类只能抛出和父类相同的或者父类异常的子类异常及其 同级别的异常

四、手动抛出异常(throw)

public static void str2Date(String strDate) throws ParseException, FileNotFoundException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		//将获取的字符串的时间 转换为Date
		Date d = sdf.parse(strDate);
		System.out.println(d);
		//throw new NullPointerException("抛出异常对象 空指针异常");
		throw  new FileNotFoundException("文件不存在的编译期异常");
	}

在抛出的时候 必须注意抛出的是异常对象 也就是必须new
1.注意:
1 手动抛出运行时异常 那么此时不需要在方法的声明上使用throws进行抛出
2 手动抛出编译期异常 此时必须将异常类型在方法的声明上使用throws 进行抛出给方法的调用者

2.throw 和throws的区别:

1 从使用的位置上:throws 方法的声明上  throw用在方法内部
2 抛出的异常类型:throws 抛出的是类型 throw 抛出的是对象
3 抛出的数量上:throws  可以抛出多个  throw 一次只能抛一个对象

3.throw的主要用途:

①异常类型的转换:

//将运行时异常转换为编译期异常
throw new Exception( new NullPointerException("抛出异常对象 空指针异常"));
//编译期异常转换为运行时异常
throw new RuntimeException(new FileNotFoundException("文件不存在的编译期异常"));

②自定义异常的抛出:
参考已知的运行时异常和编译期异常源文件写

运行异常: 在这里插入图片描述
编译异常:
在这里插入图片描述
例:

class MyException extends Exception { 
    static final long serialVersionUID = 13465653435L; 
    private int idnumber; 
    public MyException(String message, int id) { 
        super(message); 
        this.idnumber = id; 
    } 
    public int getId() { 
        return idnumber; 
    } 
}
public class MyExpTest { 
    public void regist(int num) throws MyException { 
        if (num < 0) 
            throw new MyException("人数为负值,不合理", 3); 
        else 
            System.out.println("登记人数" + num); 
    } 
    public void manager() { 
        try { 
            regist(100); 
        } catch (MyException e) { 
            System.out.print("登记失败,出错种类" + e.getId()); 
        } 
        System.out.print("本次登记操作结束"); 
    } 
    public static void main(String args[]) { 
        MyExpTest t = new MyExpTest(); t.manager(); 
    } 
}

五、总结:异常处理5个关键字

在这里插入图片描述
世界上最遥远的距离,是我在if里你在else里,似乎一直相伴又永远分离;
世界上最痴心的等待,是我当case你是switch,或许永远都选不上自己;
世界上最真情的相依,是你在try我在catch。无论你发神马脾气,我都默 默承受,静静处理。到那时,再来期待我们的finally。

六、本节随堂练习链接:

添加链接描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!