IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 【小白学Java】D27》》》程序的异常处理 try - catch & throw & throws& 自定义异常 -> 正文阅读

[Java知识库]【小白学Java】D27》》》程序的异常处理 try - catch & throw & throws& 自定义异常

一、什么是异常?

????????异常就是不正常的意思。就像生活中,正在路上行使的汽车,遇到了故障,发动机突然抛锚停止了运转,导致汽车不能正常的行驶。这样的情况,在程序开发过程中就叫做”异常“。异常就是指在程序的执行过程中出现的非正常的情况,而这种非正常的情况最终会导致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.1throw new的是RuntimeException类对象或者是其子类的对象
             那么就可以不处理,因为默认会交给JVM来处理
                            (jvm打印出异常对象的信息并且中断程序)
      3.2throw 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){
      //1.使用throw抛出异常
      
      //1.1 空指针异常 NullPointerException
      if(array ==null){
          throw new NullPointerException("数组为空");
      }
      
      //1.2 数组下标越界异常ArrayIndexOutOfBoundsException
      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);
//查看指定引用对象不是null,对传递过来的参数对象判断是不是为空

源码:
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.多个异常一次性捕获,一次性处理(捕获一次,处理一次)

举例说明:

//1.多个异常分别处理
//处理异常1
try{
          //定义一个数组下标越界异常
          int[]  ints={1,2,3,4,5,6};
          int anInt = ints[6];
          System.out.println(anInt);
          //ArrayIndexOutOfBoundsException: 6

      }catch (ArrayIndexOutOfBoundsException e){
          System.out.println(e);
      }
//处理异常2
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);
        //IndexOutOfBoundsException: Index: 6, Size: 6
    }catch (IndexOutOfBoundsException e){
        System.out.println(e);
    }
// 2.多个异常一次性捕获,然后分别处理(一次捕获,多次处理)
try{
    //定义一个数组下标越界异常
    int[]  ints={1,2,3,4,5,6};
    int anInt = ints[6];
    System.out.println(anInt);
    //ArrayIndexOutOfBoundsException: 6

    //定义一个集合下标越界异常
    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);
    //IndexOutOfBoundsException: Index: 6, Size: 6
}catch (ArrayIndexOutOfBoundsException e){
    System.out.println(e);
}catch (IndexOutOfBoundsException e){
    System.out.println(e);
}
/*
* 使用一次捕获多次处理时要注意:
* 1.如果catch里面定义的异常变量之间有着子父类的关系,
*     那么子类的异常就必须要写在父类之上,否则try中抛出的异常对象
*     系统会由上向下执行catch来捕获这个异常并处理异常,默认会处理父类异常而不会处理子类异常
*    例如: ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException
* */
//3.多个异常一次性捕获,一次性处理(捕获一次,处理一次)
try{
    //定义一个数组下标越界异常
    int[]  ints={1,2,3,4,5,6};
    int anInt = ints[6];
    System.out.println(anInt);
    //ArrayIndexOutOfBoundsException: 6
    //定义一个集合下标越界异常
    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);
    //IndexOutOfBoundsException: Index: 6, Size: 6
} catch (IndexOutOfBoundsException e){
    System.out.println(e);
}

(2)、子父类异常的注意事项

  • 如果父类抛出了多个异常,那么子类在重写父类方法时就必须要抛出和父类相同的异常 或者父类异常的子类 或者不抛出异常
  • 如果父类方法中没有抛出异常,那么子类重写父类方法时,就也不能批出异常。若子类此时产生了异常那么只能捕获处理try-catch,而不能声明批出异常。
public class fuClass {
    //function1抛出多个异常
    public void function1() throws NullPointerException,IndexOutOfBoundsException{}
    //function2抛出多个异常
    public void function2() throws NullPointerException,IndexOutOfBoundsException{}
    //function3抛出多个异常
    public void function3() throws NullPointerException,IndexOutOfBoundsException{}
    //function4没有抛出异常
    public void function4(){}
}
class ziClass extends fuClass {
       // 重写方法,抛出与父类相同的异常
        public void function1() throws NullPointerException,IndexOutOfBoundsException{}
        //重写方法,抛出父类异常的子类异常
        public void function2() throws StringIndexOutOfBoundsException{}
        //重写方法,不批出异常
        public void function3(){}
/*
如果父类方法中没有抛出异常,那么子类重写父类方法时,就也不能批出异常。
若子类此时产生了异常那么只能捕获处理try-catch,而不能声明批出异常。*/
        public void function4(){
            try{
                //可能出现异常代码
            }catch (ArrayIndexOutOfBoundsException e){
                //自己处理异常
            }
        }
        
}

五、自定义的异常类

????????自定义异常也就是自己定义一个异常来满足当前代码的需求

自定义异常类格式1:
//自定义编译时期的异常类,若方法内部抛出了异常,
//  那么方法调用者就要处理这个异常 try-catch  或者 throws
public class XXXException extends Exception {
		//添加无参构造方法
		//添加带异常信息的构造方法
}

自定义异常类格式2:
//自定义运行时期的异常类,若方法内部抛出了异常,
//那么方法不需要处理异常,而是把异常抛JVM来处理(中断处理)
public class XXXException extends RuntimeException {
		//添加无参构造方法
		//添加带异常信息的构造方法
}




制作不易,各位友友们,大佬们给点鼓励!

点赞👍 👍 👍 收藏+关注 一键三连走起!

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-22 14:00:25  更:2021-07-22 14:01:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 20:19:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码