异常体系
一、 异常
关于异常,一旦程序出现了错误或异常,那么程序就直接结束了,处理异常的目的在于能让程序正常执行。
所谓的异常就是在整个Java程序中出现的各种错误或异常
关键词:Throwable 所有异常的老大
概念总结:Throwable包含两大模块(错误和异常),所有的错误或异常只有归属到Throwable体系下才能被虚拟机识别
错误(Error):所有的错误类后缀都是Error,错误的出现往往意味着虚拟机本身出现了问题,例如:
OutOfMemoryError(内存溢出错误),StackOverflowError(堆栈内存溢出)
异常(Exception):所有的异常类后缀都是Exception,分编译时期异常和运行时异常
看错误的方式或顺序:
二、看错误的方式或顺序:
1、先看错误类型,例如:NullPointerException
2、查找问题肯能出现的地方–排查
a、先找自己项目对应的包名
b、出现错误的顺序是倒过来的,第一行往往就是最终出现问题的地方
3、验证变量或对象等值是否正确时,有两种方式可以使用
a、使用输出语句
b、断点调试
异常的处理方案有哪些?
方案一:捕获该问题并进行处理 – 自己处理
package cn.yunhe.exception;
/**
* 异常处理方案:
* 1、捕获
* try{可能会出现异常的代码块}catch(异常类型 变量名){异常的处理方案}finally{最终必然会执行的代码块}
* 可以捕获多个异常,只需要多个catch即可,当有多个异常的时候,对于已知的异常建议针对性的捕获,未知的使用Exception处理
* 当存在多个异常时,范围较大的写在最后面
* 2、抛出
*/
public class ExceptionDemo {
public static void main(String[] args) {
int[] arr = {1,5,3,6};
printIntArr(arr);
System.out.println("--over--");
}
/**
* 打印int类型的数组
* NullPointerException 空指针异常
* 空指针是java中最简单的异常也是最难的异常也是最常见的异常
* 空指针一定是对象为空,找到出现错误的行,只需要在该行中找对象即可
*
* 一旦程序出现了异常,在没有处理的情况下程序就直接终止了
* @param arr
*/
public static void printIntArr(int[] arr){
try {
if(null != arr) {
for(int i=0;i<arr.length;i++) {
System.out.println(arr[i]);
}
}
System.out.println(arr[7]);
}catch(NullPointerException e) {
e.printStackTrace();
}catch(ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
System.out.println("错误信息:"+e.getMessage());
}catch(Exception e) {
e.printStackTrace();
}finally {
//数据库连接关闭、IO流的连接关闭
System.out.println("---一定会执行----");
}
}
/**
* syso(test())结果是什么,原因
* @return
*/
public static int test() {
int count = 1;
try {
int a = 1/0;
return count++;
}catch(Exception e) {
e.printStackTrace();
}finally {
return ++count;
}
}
思考:当有多个异常存在且知道具体的异常时,应该选择全部都写还是直接用Exception处理?
回答:建议如果已知了具体的异常就分别单独捕获处理,当出现未知异常时使用Exception
注意:当出现多个异常且有上下级(继承)关系时,那么大的要放在后边
finally中的代码块是最终必然会执行的代码,通常用于io流关闭或数据库连接对象的关闭
方案二:抛出/声明 – 谁用谁处理
throw和throws的区别:
1、throw是用来抛出异常对象的,throws用来声明异常的
2、throw在方法内的,throws是在方法上的
3、throws可以同时声明多个异常,中间逗号隔开
package cn.yunhe.exception;
/**
* 自定义异常如何能加入异常体系中,因为虚拟机只能识别异常体系中的异常及错误
*
* 不建议直接继承Throwable,因为Throwable包含了错误及异常,自定义的是异常,不应该含有错误相关的信息
*/
public class MyException extends Exception{
public MyException() {}
public MyException(String s) {
super(s);
}
}
package cn.yunhe.exception;
import org.apache.log4j.Logger;
public class ExceptionDemo {
private static final Logger LOGGER = Logger.getLogger(ExceptionDemo.class);
public static void main(String[] args) throws MyException {
logTest();
}
/**
* jdk中已经提供的异常,虚拟机是可以自动识别到的,不需要显示声明,这种方式可以称为隐式声明
* 如果想要显示的声明异常,需要用到两个关键字:throws throw
* throw 抛出 抛的是异常对象
* throws 声明 声明的是异常类的类型,当有多个异常需要声明时,使用逗号隔开
*
* 捕获和抛出的区别点:
* 捕获:出现异常后进行了捕获,那么程序仍然可以正常运行
* 抛出:抛出仅仅只是将问题抛出去了,对抛出去的异常如果没有进行捕获,那最终还是交由了虚拟机来处理,结果就是报错,停止运行
*/
public static void method() throws ArithmeticException,NullPointerException{
//模拟异常处理,此处需要手动制造异常
//int a = 1/0;
boolean flag = true;
if(flag) {
throw new ArithmeticException("除数不能为0");
}else {
throw new NullPointerException("空指针异常");
}
}
/**
* 自定义异常必须要进行声明
* @throws MyException
*/
public static void myMethod() throws MyException{
throw new MyException("自定义异常");
}
public static void logTest() {
try {
int a = 1/0;
} catch (Exception e) {
LOGGER.debug(e.getMessage());
}
}
}
三、 自定义异常
系统提供的异常是比较常见,但是异常的信息并不是很详细
为了可以按照指定的想法和需求的变更更好的处理异常,也可以通过自定义异常来进行异常处理
原则:想要让自定义的类具有可抛性,那就需要继承Exception[RunntimeException]
思考:为什么不直接继承Throwable?
原因:Throwable中还包含了Error,自定义的异常通常是在程序运行时使用的,因此不具备错误的特征
关于自定义异常想要被虚拟机识别需要满足以下条件:
1、具有可抛性
2、需要抛出对应的异常 — 出现了异常
3、需要声明该异常 – 告诉调用者有异常存在