什么是异常?
Java程序在运行时出现的问题就叫异常
jdk中将异常一新封装成了一个个的类,当出现问题时,就会创建异常对象,抛出异常信息(问题原因、位置)
1.异常
1.1异常的继承体系
Throwable 是所有错误(error)和异常(Exception)的父类
错误(error)是程序运行过程中出现的严重问题(内存不够),只能修改代码避免这种错误
Exception 是Throwable 的子类,用来表示java程序中可能出现的异常,并要求对异常进行合理的处理
RuntimeException 和CheckedExceptions 两个是Exception的子类
RuntimeException及其子类 (运行时异常) java运行过程中出现的异常
CheckedExceptions 编译时异常
1.2异常和错误的区别
异常:是指程序在编译、运行期间发生了某种异常,可以对异常进行具体的处理,如果不处理异常,程序会结束
错误:是指程序运行时发生了某种错误,Error错误通常没有具体的处理方法,一般情况下错误都发生在JVM,我们无法处理
错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译时也检查不到
1.3 异常处理
1.jvm默认处理方式
一旦发生异常,产生异常代码的下面的代码就不再执行
public class Test {public static void main(String[] args) {
// 5.jvm 接收到异常后,按默认处理方法处理
// int[] arr=new int[1000*1000*1024];
// System.out.println(arr[0]);int [] arr=new int[3];int j=method(arr); //3.main方法接收到方法跑过来的异常对象//4.jvm 当前main方法有没有处理这个异常的代码,//如果没有,继续抛给main方法的调用者,这里指的是jvmSystem.out.println(j);}public static int method(int[] arr){int i=arr[3]; //1.当程序运行到arr[3]时,jvm检查有没有索引3,// 没有jvm会自动抛出一个异常.ArrayIndexOutOfBoundsException//2.检查method方法有没有处理这个异常的代码,// 没有找到,继续把这个异常抛给method的调用者return i;}
}
```
1.4编译时异常和运行时异常
⑴运行时异常:RuntimeException及其子类
IndexOutOfBoundsException
NullPointerException 空指针异常
ClassCastException 类型转换异常
运行时异常程序员可以不去处理,当异常出现时,虚拟机会处理
⑵编译时异常:非RuntimeException及其子类的异常。就在编译阶段会出现的异常
ClassNotFoundException
FileNotFoundException
编译时异常又叫做检查性异常,如果我们不处理,程序是不能被编译通过的,在idea中也会出现一条红线。因此编译时异常程序员必须处理
1.5 处理异常
捕获:java对异常有针对性额语句进行捕获,对出现的异常进行指定方式处理
格式:
try{
//可能出现异常的代码
}catch(异常类 变量){
//遗产处理语句
}
int i=10;
int j=0;
int [] arr=null;
try {j=arr[3];int s = i / j;
}catch (ArithmeticException e){System.out.println("算术异常");e.printStackTrace();
}catch (NullPointerException e){System.out.println("空指针异常");
}catch (Exception e){System.out.println("异常");}
多个catch的异常不能相同,如果异常存在子类父类关系,子类在上面,父类在下面
1.5.1 finally代码块
无论try是否发生异常,finally语句一定会执行
格式:
try{
//可能出现异常的代码
}catch(异常类 变量){
//遗产处理语句
}finally{
//无论try是否发生异常,finally语句一定会执行
一般finally里面里释放资源(io,数据库连接)的代码块
}
1.6 抛出异常 throw
在java中,提供这个throw关键字,用力抛出一个指定的异常对象。
1.创建一个异常对象
2.将这个异常对象告诉调用者:throw 异常对象
public static void main(String[] args) { //5.jvm 接收到异常后,按默认处理方法处理
// int[] arr=new int[1000*1000*1024];
// System.out.println(arr[0]);//int [] arr=new int[3];int[] arr=null;int j=method(arr,3); //3.main方法接收到方法跑过来的异常对象//4.jvm 当前main方法有没有处理这个异常的代码,//如果没有,继续抛给main方法的调用者,这里指的是jvmSystem.out.println(j);}public static int method(int[] arr,int i){if(arr==null){throw new NullPointerException();}if(i>=arr.length){// return -1;throw new ArrayIndexOutOfBoundsException();}if(i<0){throw new ArrayIndexOutOfBoundsException();}int j=arr[i]; //1.当程序运行到arr[3]时,jvm检查有没有索引3,// 没有jvm会自动抛出一个异常.ArrayIndexOutOfBoundsException//2.检查method方法有没有处理这个异常的代码,// 没有找到,继续把这个异常抛给method的调用者return j;}
1.7 声明异常 throws
public static int method(int[] arr,int i) throws NullPointerException,ArrayIndexOutOfBoundsException
如果在方法内部抛出编译时异常,没有捕获,方法上必须使用throws 声明,让调用者处理
1.8 异常常见方法
printStackTrace的堆栈跟踪功能显示出程序运行到当前类的执行流程
/*** Returns the detail message string of this throwable.* @return the detail message string of this {@code Throwable} instance* (which may be {@code null}).*/public String getMessage() {return detailMessage;}//返回该异常的详细信息public void printStackTrace() {printStackTrace(System.err);}//在控制台输出该异常的的名字和信息、以及出现的位置
2.自定义异常
自定义的异常用法通常包含四步:
1.定义异常类 2.写继承关系 3.空参构造 4.代参构造
如下:我自定义了一个异常类NameFormatException,用来在用户年龄错误时抛出
public class NameFormatException extends RuntimeException{public NameFormatException() {}public NameFormatException(String cause) {super(cause);}
}public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {//判断年龄是否符合if(name.length()<3&&name.length()>10){throw new NameFormatException(name+"ss");}this.name = name;}public int getAge() {return age;}public void setAge(int age) {if(age<18&&age>30){throw new RuntimeException();}this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
注:文章来自闫军锋老师课堂笔记扩充修改