异常概述
在java中程序的运行往往会因为设计或者编写过程中引起一些错误的操作,这些错误信息主要包含两种类型
-
错误(Error):通常是JVM内部错误,或者资源耗尽等一些无法从本质上解决的问题(严重问题)
-
异常(Exception):因为一些编程错误或者外在因素引起的可以被修复的问题
Error和Exception都是从Throwable类继承过来
异常分类(Exception)
java中的异常主要包含两种类型:
-
运行时异常(RuntimeException):在程序运行时才会出现
-
java.lang.NullPointerException<空指针异常>
-
java.lang.IndexOutOfBoundsException< 索引超出范围>
-
java.lang.ArrayIndexOutOfBoundsException<数组索引越界>
-
java.lang.NumberFormatException<转换为数值类型异常>
-
java.lang.ClassCastException <类型转换异常>
-
java.lang.ArithmeticException <算数异常>
-
-
-
-
-
一般异常(检查异常):在编译期就显式的通知程序员必须处理
-
java.lang.ClassNotFoundException<类未找到异常>
-
java.io.IOException<IO异常>
-
异常处理
java程序在运行时或者编译时如果出现异常,则会产生异常对象,对于该异常对象的处理方法,通常包含两种解决方法:
-
异常抛出(throws)
-
异常捕获(try...catch...fianlly)
java中的异常处理通常包含以下关键字:
-
throw :一定会抛出该异常,通常出现在方法内部用于显式抛出
-
throws :抛出有可能出现的异常,出现在方法声明区域(在参数列表后面)
-
try :try语句块一般用于将有可能出现异常的语句包裹
-
catch:处理try语句块中可能出现的异常,一旦异常产生则进入对应的catch块(可以catch多种异常)
-
finally:finally语句块中内容无论是否出现异常,都会执行,一般用执行资源清理与回收
思考以下方法执行之后i的结果?
public static int m2(){ int i = 10; try{ i = 20; //System.out.println(i/0); return i; }catch(Exception e){ e.printStackTrace(); }finally{ i = 30; System.out.println("执行finally"); } return i; }
finally一般常用于,文件资源的回收,网络资源的关闭,数据库连接相关资源的回收
思考:java是否存在内存泄漏问题?
理论上java不存在内存泄漏,因为,java中存在GC机制,jvm会在适当的时候对申请内存空间释放;但是对于第三方的资源(文件,网络,数据库)访问GC无法自动关闭,通常都需要由程序员手动关闭或者释放,如果这些资源没有正常回收就有可能引起系统内存泄漏,通常对于以上资源的清理都放在finally处理。
自定义异常
在实际项目开发中,jdk自带的异常无法完全满足项目中的业务需求,此时可以通过对Exception类或者其子类继承,从而扩展自定义的异常类,比如有以下需求:
完成一个银行账户的转账逻辑,有账户A,B,此时账户A若向账户B转出一定金额,如果A账户余额不足则要抛出一个异常,但是JDK中并未包含该含义的异常类,因此可以自定义异常:LessMoneyException,如下:
LessMoneyException.java
public class LessMoneyException extends Exception{ public LessMoneyException() { } public LessMoneyException(String msg){ super(msg); } }
自定义异常一般对Exception类或其子类继承后需要定义默认构造器,以及包含异常信息(String参数)的构造器
Account.java
public class Account { private double cash; public Account(double cash) { this.cash = cash; } /** * 执行转账逻辑,并抛出有可能出现的余额不足异常 */ public void changeOut(Account c,double money) throws LessMoneyException{ if(this.cash >= money){ //目标账号金额增加 c.cash = c.cash + money; //当前账户金额减少 this.cash = this.cash - money; }else{ throw new LessMoneyException("骚年,余额不足,请充值!!!"); } } }
关于异常处理
对于异常抛出,被抛出的异常必须由后续的调用者处理(继续抛出,捕获)
存在继承关系的子类中不能抛出超出父类抛出的异常范围
如果父类方法没有抛出任何异常,则子类重写父类方法时只能对产生异常捕获
如何快速定位异常出现的位置:
观察异常的类型名称
观察异常的关键字(异常名之后)
第一次出现异常的代码行数