1、异常的概念
(来自百度)在 java 中把导致程序中断运行的情况分为两种,一种就是异常,而另外一种叫做错误。所有异常的基类是Exception,错误的基类是Error。Exception是在java程序中可以编码进行控制的,具有可编程性,而Error是指Java运行时系统来显示与运行时系统本身有关的错误,Error对于程序员来说是灾难性的,程序无法控制,比如jvm堆栈溢出错误,操作系统分配内存错误等。不管是Exception还是Error,他们的共同父类是java.lang.Throwable(可抛出的) 类。
异常是指在程序运行期可能出现的非正常情况,这些情况将导致程序出错,这种出错不同于代码编写错误或程序算法出错,代码编写错误无法完成编译,而程序算法出错计算将取得错误的结果。程序出现异常时,缺省会直接造成程序的中断运行,提前预知这种异常的可能性可以补充异常处理的逻辑,从这个角度出发,异常也是一种行之有效的逻辑处理机制,在程序中声明异常或主动抛出异常也很常见。
简而言之,为了提高程序的健壮性,异常需要由程序员处理。
2、什么是Java中的异常
- 代码正常运行不会出问题,但是遇到意外,参数变量,不符合要求,发生意外,代码终止运行
- 代码中的异常处理好了,代码就可以顺利的继续运行!
3、先看看什么是异常
System.out.println(1/0); // java.lang.ArithmeticException: / by zero
String str = null;
System.out.println(str.length()); // java.lang.NullPointerException
int[] arr = {1,2};
System.out.println(arr[arr.length]); // java.lang.ArrayIndexOutOfBoundsException: 2
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd HH时mm分ss秒 E");
sdf.parse("fsdfsdf"); // ParseException
4、异常的体系结构
5、异常的处理方式
5.1、自己处理[捕获异常]
1.try-catch的语法结构及链式结构多异常处理方式
try{ //可能产生异常的代码 }catch( 捕获的异常类型 e ){ //e是形式参数 //该异常捕获之后要做的操作 }catch( 捕获的异常类型 e ){ //e是形式参数 //该异常捕获之后要做的操作 }finally{ //异常发生之后一定会执行到的语句块:①流资源关闭②释放锁 } |
语句块执行顺序:
- 顺序执行:进入异常捕获语句块
- 如果产生异常,执行catch捕获,捕获到对应异常,并且对应catch后面的代码块
- finally语句块一定会执行到:前提前面语句没有执行System.exit(0)退出虚拟机
5.2、异常信息处理方式二抛出异常
语法结构:方法后面使用throws 需要抛出的异常类型
示例:
public static void main(String[] args) throws Exception{ // 抛出了异常
new SimpleDateFormat().parse("fsfsdfsdf");
}
抛出异常的注意事项:
- 方法抛出运行时异常,在方法头可以不用抛出异常
- 方法抛出编译时异常:方法必须处理异常,或者抛出同类异常,或者抛出异常该异常的父类类型异常
6、获得异常信息的方式
6.1异常捕获分析
- 写多个捕获异常的语句块,链式结构捕获多异常,根据不同的异常,做不同的处理
- 捕获异常可以写异常的父类,也可以捕获到对应子类的异常
- catch(捕获的异常类型 e)捕获的异常实际捕获一个异常对象,该对象e可以在catch语句块直接使用
6.2、获取信息的方式
方式1: System.out.println(e); 方式2: System.out.println(e.getMessage()); 方式3: e.printStackTrace(); // 获取并打印异常信息最常用的方式 |
7、finally结构
7.1、finally语句块介绍
- try-catch语句块可以用写finally,处理异常之后finally语句块一定会执行到
- finally语句块中,一般用来处理什么内容
- 关闭流资源
- 释放锁
7.2、注意事项 :
- 一般不要在finally里面写返回语句,程序难理解
- finally语句之前,如果有执行退出虚拟机,也是不会执行finally语句块
public static void main(String[] args) {
System.out.println(get(0));
}
public static int get(){
int i = 10;
try { // 只在try写返回值:只看结构不看值:报错没有返回语句
System.exit(0);
i = 20;
return i; // 结束方法,返回值
} catch (Exception e) {
i = 30;
return i; // 存在finally语句块,虽然return叫做结束方法,但是其实还没有完全结束 ,变量i,返回值,处于一个缓存的状态
} finally { // finally先执行,后面才执行的return
i = 40; // 等于覆盖了返回值变量里面存的值
return i; // 修改的返回值的缓存
}
}
8、主动抛出异常
8.1、为什么需要主动抛出异常
8.2、主动抛出异常示例
方法内部主动创建异常抛出:throw new SelfException("账户已经存在,请重新输入");
账号登陆示例:
static String[] names = {"XX","OO"};
public static void main(String[] args) {
login("XX");
}
public static void login(String name){
for (String string : names) {
if(name.equals(string)){ // 已经存在一个意外的情况了
//意外情况,主动产生一个异常信息
throw new NullPointerException("阁下账号已经被人使用");
}
}
System.out.println("恭喜您:"+name+"账号可以使用");
}
9、自定义异常
9.1、为什么需要自定义异常:
1、java已经写好很多异常,但不能满足开发中所有异常描述的需求,所以需要自定义异常
9.2、自定义异常的方式
- 自定义类继承异常类
- 参照其他异常通过Exception设置异常提示信息
public class SelfException extends Exception{ SelfException(String msg){ super(msg); } }
9.3、自定义异常使用
static String[] names = {"周周","皇皇"};
public static void main(String[] args) throws SelfException {
login("周周");
}
public static void login(String name) throws SelfException{
for (String string : names) {
if(name.equals(string)){ // 已经存在一个意外的情况了
throw new SelfException("XXXXXX"); // 意外情况,主动产生一个异常信息
}
}
System.out.println("恭喜您:"+name+"账号可以使用");
}
9.4、throws 和 throw的区别
9.4.1、throws 处理异常
- 在方法头抛出异常
9.4.2、throw 抛出异常
- 开发代码存在意外的情况,自己主动抛出异常[产生异常]
- 在方法内部 throw new NullPointException();