异常就是Java程序出现了不正常的情况。
程序的异常:Throwable
严重问题:Error 我们不处理,一般这种问题都是很严重的,比如内存溢出
问题:Exception
编译期问题:不是RuntimeException的异常 必须进行处理的,因为不处理,编译就不能通过
运行期问题:RuntimeException 这种问题我们也不处理,因为是代码不严谨的问题,需要修正代码。
如果程序出现了问题,我们没有做任何处理,最终jvm会做出默认的处理:把异常的名称,原因及出现的问题等信息输出在控制台;同时会结束程序。
我们可以自己进行异常处理方案:
A:try…catch…finally处理格式:
try{
可能出现问题的代码;
}catch(异常类名 变量名){
针对问题的处理;
}finally{
释放资源;
}
变形格式:
try{
可能出现问题的代码;
}catch(异常类名 变量名){
针对问题的处理;
}
注意:try里面的代码越少越好。catch里面必须有内容,哪怕是给出一个简单的提示
两个异常的处理:
(1)每一个都写一个try…catch…
(2)写一个try,多个catch:
try{
可能出现问题的代码;
}catch(异常类名 变量名){
针对问题的处理;
}catch(异常类名 变量名){
针对问题的处理;
}
一旦try里面出了问题,就会在这里把问题给抛出去,然后和catch里面的问题进行匹配,一旦有匹配的,就执行catch里面的处理,然后结束try…catch…,继续执行后面的语句(碰到第一个问题就会抛出并查找并输出,然后执行后面的。)
注意:
1.能明确的尽量明确,不要用大的来处理(Exception e)
2.平级关系的异常谁前谁后无所谓,如果出现了子父关系,父必须在后面。(如果父在前面的话,父后面的异常处理就多余了)
finally的特点:
被finally控制的语句体一定会执行,但是特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))就不会执行
finally的作用:用于释放资源,在IO流操作和数据库操作中会见到
1.final,finally和finalize的区别:
final:最终的意思,可以修饰类,成员变量,成员方法。
修饰类,类不能被继承。
修饰成员变量,变量是常量。
修饰成员方法,方法不能被重写。
finally:是异常处理的一部分,用来释放资源。
一般来说代码肯定会执行,特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))就不会执行
finalize:是Object类的一个方法,用于垃圾回收。
2.如果catch里面有return语句,请问finally的代码还会执行吗?如果会,请问是在return前还是return后。
会。前。准确的说应该是在中间。(这里的return语句返回路径已经形成,但还是会执行finally语句)
\3. try…catch…finally的格式变形:
(1)try…catch…finally
(2)try…catch
(3)try…catch…catch
(4)try…catch…catch…finally
(5)try…finally 这种格式的做法目前是为了释放资源
必须要有try
B:throws
定义功能方法时,需要把出现的问题暴露出来让调用者去处理。那么就通过throws在方法上标识。(有些时候我们没有权限去处理某个异常,有可能处理不了,所以java提供了另一种处理方案:抛出)
格式:throws 异常类名 可以跟多个,用逗号隔开
注意:这个格式必须跟在方法的括号后面。(在方法声明上抛出是为了告诉调用者我有问题) 调用者的处理方式:1.在方法上继续抛异常 2.用try…catch…
尽量不要再main方法上抛出异常
throw:程序不能继续运行,需要进行跳转时,如果出现了异常情况,我们可以把异常抛出,这个时候抛出的应该是异常的对象而不是异常的类名。
throws和throw的区别:
throws:用在方法声明后面,跟的是异常类名;可以跟多个异常类名,用逗号隔开;表示抛出异常,由该方法的调用者来处理;throws表示出现异常的一种可能性,并不一定会发生这些异常
throw:用在方法体内,跟的是异常对象名;只能抛出一个异常对象名;表示抛出异常,由方法体内的语句处理;throw则是抛出了异常,执行throw则一定抛出了某种异常
处理异常的原则:如果该功能内部可以将问题处理,用try;如果处理不了,交由调用者处理,这是用throws。后续程序需要继续运行就try;后续程序不需要继续运行就throws
编译时异常和运行时异常的区别:
编译时异常:Java程序必须显示处理,否则程序就会发生错误,无法通过编译
运行时异常:无需显示处理,也可以和编译时异常一样处理
在try里面发现问题后,jvm会帮我们生成一个异常对象,然后把这个对象抛出,和catch里面的类进行匹配。如果对象是某个类型的,就会执行该catch里面的处理信息。
Throwable中的方法:
public String getMessage() 获取异常信息,返回字符串。
public String toString() 获取异常类名和异常信息,返回字符串:此对象的类的name(全路径名)
+ “: ” (冒号和一个空格)
+ 调用此对象getLocalizedMessage()方法的结果(这里默认返回的是getMessage()的内容)
printStackTrace() 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。把信息输出在控制台
printStackTrace(PrintStream s) 通常用该方法将异常内容保存在日志文件中,以便查阅。
自定义异常:当java中没有对应的异常,需要我们自己来定义一个异常要想自己写的类是一个异常类,就必须继承自Exception(非运行时异常,再调用时需要处理异常)或者继承自RuntimeException(运行时异常,再调用时不用处理异常)
自定义异常不用写方法体(有时候需要写构造方法:无参,带参:super(message);)
注意事项:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws
运行时异常:RuntimeException类及其子类的异常,是非受检异常,如NullPointerException、IndexOutOfBoundsException等。由于这类异常要么是系统异常,无法处理,如网络问题;要么是程序逻辑错误,如空指针异常;JVM必须停止运行以改正这种错误,所以运行时异常可以不进行处理(捕获或向上抛出,当然也可以处理),而由JVM自行处理。Java Runtime会自动catch到程序throw的RuntimeException,然后停止线程,打印异常
异常 | 说明 |
---|---|
ArithmeticException | 算术错误,如被0除 |
ArrayIndexOutOfBoundsException | 数组下标越界 |
ArrayStoreException | 数组元素赋值类型不兼容 |
ClassCastException | 非法强制转换类型 |
IllegalArgumentException | 非法参数类型 |
IllegalMonitorStateException | 非法监控操作,如等待一个未锁定的线程 |
IllegalStateException | 环境或应用状态不正确 |
IllegalThreadStateException | 请求操作与当前线程状态不兼容 |
IndexOutOfBoundsException | 某些类型索引越界 |
NullPointerException | 非法使用空引用 |
NumberFormatException | 字符串到数字格式非法转换 |
SecurityException | 试图违反安全性 |
StringIndexOutOfBounds | 试图在字符串边界之外索引 |
UnsupportedOperationException | 遇到不支持的操作 |
BufferOverflowException | IO操作的 |
非运行时异常,受检异常(checked exception):RuntimeException以外的异常,类型上都属于Exception类及其子类,是受检异常。非运行时异常必须进行处理(捕获或向上抛出),如果不处理,程序将出现编译错误。一般情况下,API中写了throws的Exception都不是RuntimeException
异常 | 意义 |
---|---|
IOException | |
SQLException | |
FileNotFoundException | |
NoSuchFileException | |
NoSuchMethodException | |
InterruptedException | 一个线程被另一个线程中断 |
InstantiationException | 试图创建一个抽象类或抽象接口的对象 |
IllegalAccessException | 对一个类的访问被拒绝 |
CloneNotSupportedException | 试图克隆一个不能实现Cloneable接口的对象 |
ClassNotFoundException | 找不到类 |
打印异常
1 e.getMessage() ; 只会获得异常的名称。比如说NullPoint 空指针,就告诉你说是空指针
2.e.toString(): 获得异常种类和错误信息
3.e.printStackTrace(); 在控制台打印打印出详细的异常信息,异常名称。便于调试
e.printStackTrace()是打印整个Exception轨迹栈,相当于System.out.print(e.getStackTrace().toString())
4.e初始化,也就是实例化Exception类型的对象,e是此对象引用名称。然后e(引用)会自动调用Exception类中指定的方法,也就出现了e.printStackTrace()
如果异常是用无参构造器构造,后续又没有设置message的话一般就是null,如果用带String参数的构造器构造的话,返回的就是那个参数