一、什么是异常?
????????异常就是不正常的意思。就像生活中,正在路上行使的汽车,遇到了故障,发动机突然抛锚停止了运转,导致汽车不能正常的行驶。这样的情况,在程序开发过程中就叫做”异常“。异常就是指在程序的执行过程中出现的非正常的情况,而这种非正常的情况最终会导致JVM(java虚拟机)非正常的停止。 主要表现为在集成开发环境中,代码上会出现红色的下划线亦或者是红色的波浪线,在控制台(console)上程序会运行中断并会抛出一个异常信息。
????????像在Java等面向对象的编程语言中,异常本身其实就是一个类(异常类),而产生异常其实就是创建了一个异常对象,并且抛出了该异常对象。Java中对异常的处理方式是中断处理。
????????有一个很关键的点,朋友们要注意了,特别是初学者最容易搞混了。我们要注意,导致出现异常的错误原因,并不包括语法错误。 我们通常写的源代码就是”.java“后缀的文件,都需要经过java编译器也就是JVM编译过后产生的一个”.class“后缀的文件,最终才能运行出来。而这里,如果是语法出现错了,那么就会导致代码的编译不通过,就不会产生字节码文件,那么程序就根本运行不了,前面说的异常就是抛出一个异常类的异常对象,而现在程序无法运行就不会产生并抛出异常类的对象,所以说,异常并不包括语法错误。
那么,今天呢,小北有幸能和大家分享,小北在学习异常处理时所避的坑。 小北在学习时,已经整理好了自己的学习笔记,Java中的异常处理相关的知识以及初学者需要注意,需要重点掌握的知识点。今天分享给大家。 希望各位,走过的路过的友友们,大佬们,给小北点儿鼓励,制作不容易 点赞👍 👍 👍 收藏+关注,一键三连走起!
二、异常的体系及分类
????????异常机制就是用来帮助我们找到程序中出现的问题。Java中异常有一个根类,是java.lang.Throwable类,所有的异常都是由它继承而来的。java.lang包下的Error类和java.lang.Exception类,分别是其两个重要的子类,我们平时经常说的异常其实就是指的Exception。
java.lang.Error 就是指的很严重的错误,也就是无法处理的错误,而这种错误我们只能事先避免,否则一旦出现,我们就必须修改源代码。
java.lang.Exception: 表示异常,可以处理的错误,异常可以通过代码的方式来处理(无需修改源代码),使得程序能够继续运行,而异常是必须要处理的。 异常类有两种异常;(1)程序运行期间的异常,也就是说在代码运行期间会检查有无异常产生,但是编译时,编译器不会进行检查。(2)程序编译期间的异常,在程序编译期间进行检查,如果没处理异常,那么就会导致编译失败。
三、异常的产生过程分析
看个例子:
public static void main(String[] args) {
int[] array={1,2,3,4 };
int a= printelement(array,4);
System.out.println(a);
}
public static int printelement(int[] array,int i){
int a= array[i];
return a;
}
(Ctrl+Shift+F10) 执行报错: 我们来分析一下异常的产生过程: 第一步:main方法中int a= printelement(arr,4); 调用了printelement(int[] arr,int i) 方法,来访问数组中的下标index=4 的元素,但是数组下标是从0开始的没有4索引,那么这时JVM(java虚拟机)就会检测到程序出现异常,JVM处理步骤是这样的: 1.JVM会根据当前出现的,异常的产生原因,创建一个异常对象,并且该对象包含了产生异常的内容、原因和位置; 例如new ArrayIndexOutOfBoundsException: 4
2.因为方法printelement(int[] arr,int i) 中没有写处理异常的代码逻辑(抛出异常 / try-catch),所以JVM就会把该异常对象,抛出给调用该方法的调用者(这里是main方法)处理这个异常。
第二步:方法的调用者(main方法)接收到这个异常,若有处理异常的代码逻辑,就会处理,若没有,则继续向调用者的上级调用者抛出这个异常,直到 ” 有人“ 来处理这个异常。
第三步:main方法的调用者是JVM,那么JVM就会接收到这个异常对象并处理,处理逻辑是这样的:
1.将异常对象的信息(内容、原因、位置)以红色的字体打印到控制台(console)
2.JVM会中止当前正在执行的java程序,也就是程序的中断处理。
四、异常的处理
1、关键字throw
????????throw关键字,用来在指定的方法中抛出一个指定的异常对象
(1)使用格式:
throw new ...Exception("产生异常的原因“);
(2)注意:
1.throw写在方法的内部
2.throw new 对象必须是Exception类对象或者是其子类的对象
3.throw 批出的异常对象,必须处理
3.1、throw new的是RuntimeException类对象或者是其子类的对象
那么就可以不处理,因为默认会交给JVM来处理
(jvm打印出异常对象的信息并且中断程序)
3.2、throw new的是编译异常,
那么就必须处理这个异常,throws或者try -catch
public static void main(String[] args) {
int[] array1={1,2,3,4 };
int a= printelement(array1,4);
System.out.println(a);
int[] array2=null;
int b= printelement(array2,2);
System.out.println(b);
}
public static int printelement(int[] array,int i){
if(array ==null){
throw new NullPointerException("数组为空");
}
if(i<0 || i>= array.length){
throw new ArrayIndexOutOfBoundsException("找不到索引,下标越界了");
}
int a= array[i];
return a;
}
注意:上面两种异常都属于运行时异常,都默认交给了JVM来处理
2、Object类中提供的一个判空方法
public static <T> T requireNonNull(T obj);
源码:
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
有两种重载的方法如图: message------->信息
3、声明异常的关键字throws
????????声明异常就是指将问题标记出来并且报告给方法调用者。 如果方法内通过throw抛出了编译时异常,但是并没有捕获处理该异常,那么必须要使用throws关键字进行声明,让调用者来处理该异常。关键字throws运用在方法声明上,用来表示当前方法不处理异常,只是提醒该方法的调用者来处理异常(也就是指:抛出异常)
声明的格式:
修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2..[
throw new 异常类名1("产生异常的原因");
throw new 异常类名2("产生异常的原因");
...
}
使用throws关键字注意;
注意;
1.throws 关键字必须写在方法声明上
2.throws 关键字后面声明的异常必须是Exception或者是其的子类
3.在方法的内部若是抛出了多个异常类对象,
那么throws后面必须也声明对应的多个异常类
如果抛出的多个异常对象之间有着子父类的关系,
那么就直接声明父类异常就行,
4.如果调用了一个声明了批出异常的方法,那么就必须要处理该方法声明的异常
要么继续使用throws声明抛出异常交给方法的调用者来处理,
依次往上抛出,直到最终抛出给JVM来处理
要么就使用try...catch自己来处理这个异常。
使用throws关键字来抛出异常有个缺点,就是当使用throws抛出一个异常时,那么产生了该异常的代码之后的后续代码就不会在执行了,因为JVM已经中断处理了。
4、try-catch捕获异常
使用try-catch的结构方式就是用来捕获异常。
- 捕获异常:捕获异常就是指Java中对异常有着针对性的语句来进行捕获异常,并且可以对出现的异常进行指定方式的处理。
使用throws关键字声明的方法,不处理异常,而是将出现的异常抛出给方法的调用者来处理;
使用try-catch语句可以处理异常,对出现的异常以指定的方法来处理
使用格式 1:处理一个异常
try{
}catch(定义异常变量,用于接收try中的异常对象){
}
使用格式 2:处理多个异常
try{
}catch(定义异常变量1,用于接收try中的异常对象1){
}catch(定义异常变量2,用于接收try中的异常对象2){
}catch(定义异常变量3,用于接收try中的异常对象3){
}
...
使用格式 3:处理多个异常,并且最终无论有无异常产生都会执行一个代码块
try{
}catch(定义异常变量1,用于接收try中的异常对象1){
}
...
catch(定义异常变量3,用于接收try中的异常对象3){
}finally{
}
注意:
finally不能独立使用,必须要和try一起使用;
finally一般会用于对资源的释放回收处理,程序无论是否会出现异常最终都要进行资源回收释放处理。
使用try-catch注意;
- 如果try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完catch中的处理逻辑,就会继续执行try-catch之后的代码。
- 如果try中没有产生异常,那么就不会执行catch中异常的处理逐辑,执行完try中的代码后,就会继续执行try-catch之后的代码。
5.Throwable类中处理异常的3个方法
String getMessage(): 返回throwable类异常对象的简单概述。
String tostring() : 返回throwabLe类的异常对象详细描述信息(字符串)。
void printStackTrace() :
JVM打印异常对象的方法,打印的异常信息是最全面的
6.使用异常的注意事项
(1)、当有多个异常使用捕获时的处理方式:
- 1.多个异常分别处理
- 2.多个异常一次性捕获,然后分别处理(一次捕获,多次处理)
- 3.多个异常一次性捕获,一次性处理(捕获一次,处理一次)
举例说明:
try{
int[] ints={1,2,3,4,5,6};
int anInt = ints[6];
System.out.println(anInt);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
}
try{
ArrayList<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
integers.add(4);
integers.add(5);
integers.add(6);
Integer integer = integers.get(6);
System.out.println(integer);
}catch (IndexOutOfBoundsException e){
System.out.println(e);
}
try{
int[] ints={1,2,3,4,5,6};
int anInt = ints[6];
System.out.println(anInt);
ArrayList<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
integers.add(4);
integers.add(5);
integers.add(6);
Integer integer = integers.get(6);
System.out.println(integer);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
}catch (IndexOutOfBoundsException e){
System.out.println(e);
}
try{
int[] ints={1,2,3,4,5,6};
int anInt = ints[6];
System.out.println(anInt);
ArrayList<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
integers.add(4);
integers.add(5);
integers.add(6);
Integer integer = integers.get(6);
System.out.println(integer);
} catch (IndexOutOfBoundsException e){
System.out.println(e);
}
(2)、子父类异常的注意事项
- 如果父类抛出了多个异常,那么子类在重写父类方法时就必须要抛出和父类相同的异常 或者父类异常的子类 或者不抛出异常
- 如果父类方法中没有抛出异常,那么子类重写父类方法时,就也不能批出异常。若子类此时产生了异常那么只能捕获处理try-catch,而不能声明批出异常。
public class fuClass {
public void function1() throws NullPointerException,IndexOutOfBoundsException{}
public void function2() throws NullPointerException,IndexOutOfBoundsException{}
public void function3() throws NullPointerException,IndexOutOfBoundsException{}
public void function4(){}
}
class ziClass extends fuClass {
public void function1() throws NullPointerException,IndexOutOfBoundsException{}
public void function2() throws StringIndexOutOfBoundsException{}
public void function3(){}
public void function4(){
try{
}catch (ArrayIndexOutOfBoundsException e){
}
}
}
五、自定义的异常类
????????自定义异常也就是自己定义一个异常来满足当前代码的需求
自定义异常类格式1:
public class XXXException extends Exception {
}
自定义异常类格式2:
public class XXXException extends RuntimeException {
}
制作不易,各位友友们,大佬们给点鼓励!
点赞👍 👍 👍 收藏+关注 一键三连走起!
|