异常
Java程序过程中,出现的不正常的情况,出现的错误,称为异常
异常就是对象,描述那些不正常的情况,包含了这些i情况的原因、类型、描述以及位置,这些内容都封装在异常对象中
异常也是一种处理异常情况的机制,可以进行跳转、捕获、结束程序
简述
Throwable 异常体系的顶层父类
Error 错误,描述哪些无法捕获和处理的错误情况,属于非常严重的错误
Exception 异常,可捕获的和处理的列外情况
RuntimeException 运行时异常,编译阶段不做检查
jvm默认处理机制
出现异常时,jvm有默认的处理机制
说明:
1)出现异常时,将异常封装为对象,对象中包含了异常的各种消息
2)将异常返回给调用者,哪个方法出现异常,哪个方法就接收异常
3)异常一层层向上抛出,最终抛给主方法
4)如果主方法不能处理,就将异常抛给jvm
5)jvm使用标准错误流,将异常打印到控制台
捕获异常
try……catch
说明:
1、try代码块中出现异常时,交给catch处理,如果是catch内定义的异常就交给catch,不然就交给jvm;
2、try代码块没有出现异常,就不再执行catch代码块。
try {
可能发生异常的代码
}catch(可能出现异常的类型 异常对象名) {
出现异常的处理方案
}
例如:
try {
int i = 10/0;
}catch(ArithmeticException ari) {
System.out.println("除数不能为0");
}
try……catch……catch……
说明:
1、try代码块中出现异常时,交给下面的catch代码块处理,从上到下依次匹配,是哪个catch代码块的异常类型,就交给哪个catch代码块处理。
2、如果catch代码块中都没有对应的异常,就交给jvm处理
try{
}catch(……){
}catch(……){
}catch(……){
}……
try……catch……finally
try{
……
}catch(……){
}finally{
一定会执行的代码块:
1、try中没有抛出异常
2、catch捕获了异常
3、catch不能捕获的异常
所有情况下,都会执行finally代码块
}
例如:
try {
int i = 10 / 0;
int[] arr = { 1, 2, 3 };
System.out.println(arr[4]);
} catch (ArithmeticException e1) {
System.out.println("0不能为除数");
} finally {
System.out.println("索引越界");
}
ps:finally中一般写,关闭资源的代码
try……finally
try {
……
} finally {
1、try某处抛出异常,不在执行try中后面的内容,直接执行finally
2、try没有抛出异常,执行完try再执行finally
}
try……finally可以嵌套使用:
try {
……
} finally{
……
try {
……
} finally {
……
}
}
注意:
1、没有加finally时如果catch中没有捕获异常,后面的代码都不在运行;如果捕获了异常,正常运行
2、父类异常写在子类异常的最下面(Eception要放在ArithmeticException等异常的最下面)
3、如果两个catch异常的操作是一样的,那么这两个异常是可以进行逻辑计算的
异常1 | 异常2 命名
编译时异常、运行时异常
无论是编译时异常还是运行时异常,都只有在程序运行时才可能发生异常(异常是个对象)
区别
一、继承不同
1)编译时异常,Exception以及Exception的子类类型(除RuntimeException)
2)运行时异常,RuntimeException以及RuntimeException的子类
二、解释
1)编译时异常:在编译阶段要对此异常进行检测的异常。一旦有这种异常,不给通过,必须处理(声明、捕获和处理)
2)运行时异常:在编译阶段不检测的异常。即使编译阶段有运行时异常也不会报错,可以处理,也可以不处理
异常的常用方法
大多功能都定义在顶层父类Throwable中。
那么为什么还要定义那么多子类??
发生异常时为了指明到底是什么异常,且便于和catch代码块配对
构造方法
Throwable()创建一个没有参数的异常对象
Throwable(String message)创建一个带有指定消息的异常对象
Throwable(Throwable cause)创建一个有原因异常的异常对象
Throwable(String message,Throwable cause)
成员方法
Throwable getCause()获取异常对象中的原因异常,当前异常对象的一个成员方法。如果cause不存在或者未知返回null
String getMessage()获取异常的详细信息
//出现异常的操作(比如除0)
String toString()获取异常对象的详细信息
//什么异常类型 + 出现异常的操作(比如除0)
void printStackTrace()打印异常的调用栈轨迹(方法调用的路径)
Throw
抛出异常对象,谁调用,发生异常时返回给谁(实例化异常对象,才能返回)
注意:
1)发生异常后,后面的代码不在执行(没有finally)
2)如果抛出的是编译时异常需要解决(声明throws、捕获和处理);如果是运行时异常可以不处理
Throws
抛出。表明此方法可能发生异常。将主动权交给调用者(给访问此方法的调用者讲,这里可能会发生异常,会采取什么措施,由调用者自己决定)
格式:
方法声明(……) throws 异常类型{
……
}
注意:
1、编译时异常,对外声明,对内不处理
2、运行时异常,不要声明,编译时看不见
3、声明异常时,最好精确一点(比如声明一个Throwable异常,处理起来就比较麻烦)
4、不要声明很多异常,处理麻烦
5、不要把不可能出现的异常也声明出来
自定义异常
对于某些特定的要求,jdk自带的异常类型不足以表达。比如地区要求、比如年龄要求至少18岁
步骤:
1、定义一个类,类名以Exception结尾
2、继承异常父类,Excption(编译时异常)、RuntimeException(运行时异常)
3、构造方法不能继承,需要自己写(其他的都不用写,在Throwable里面都已经设定好了)
【注意在可能发生异常的地方加throw,抛出异常】
package com.first.demos;
public class demo_自定义异常 {
public static void main(String[] args) throws IllegaleAgeException {
Person p = new Person("李四",5);
p.setAge(6);
System.out.println(p);
}
}
class Person{
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) throws IllegaleAgeException{
if(age < 18) {
//注意加throw 抛出异常
throw new IllegaleAgeException("年龄小于18岁");
}
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) throws IllegaleAgeException{
if(age < 18) {
throw new IllegaleAgeException("年龄小于18岁");
}
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
//自定义异常类
class IllegaleAgeException extends Exception{
public IllegaleAgeException() {
super();
}
public IllegaleAgeException(String message) {
super(message);
}
}
Throwable getCause()????
PS
1)【】、加粗表示重点;删除线表示已解决
2)学习记录实现,如有不妥还望指正