美文网首页
五 异常与多线程——第一节 异常

五 异常与多线程——第一节 异常

作者: 杜艳_66c4 | 来源:发表于2022-06-04 12:14 被阅读0次

1、异常概念&异常体系

Throwable 类是所有异常exception和错误error的超类,在java.lang 包中
1、Exception 编译期异常,进行编译java程序出现的问题
Exception 的子类,RuntimeException:运行期异常,
上面两种相当于程序的小毛病。把异常处理掉,程序可以继续执行
2、Error:错误, 相当于程序得了无法治愈的毛病,必须修改代码, 程序才能继续执行

Throwable中的常用方法:

1、 public void printStackTrace():打印异常的详细信息。
包含了异常的类型,异常的原因,还包括异常出现的位置,在开发和调试阶段,都得使用printStackTrace。

2、 public String getMessage():获取发生异常的原因。
提示给用户的时候,就提示错误原因。

3、 public String toString():获取异常的类型和异常描述信息(不用)。
出现异常,最简单的方式就是把异常的简单类名,拷贝到API中去查。

package exception2;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * created by apple on 2020/6/21
 * java.lang.Throwable:类是java语言中 所有错误或异常的超类
 */
public class Demo01Exception {
    public static void main(String[] args) /*throws ParseException */{
        //Exception  编译期异常 进行编译(写代码) java程序出现的问题
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;//把字符串格式的日期,解析成Date格式的日期
        try {
            date = sdf.parse("1990-09-09");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println(date);
         System.out.println("上面报错了,但是这句还能执行");

        //运行期异常
        int[] arr ={1,3,5};
       // System.out.println(arr[5]); //ArrayIndexOutOfBoundsException,索引越界异常,运行期出现的异常
        try {
            //可能会出现异常的代码
            System.out.println(arr[5]);
        }catch(Exception e){
            //异常的处理逻辑
            e.getStackTrace();
   System.out.println(e)  //ArrayIndexOutOfBoundsException
        }
    System.out.println("上面报错了,但是这句还能执行");
        //Error 错误
        int[] arr1 = new int[1024*1024*1024];
        /*
        OutOfMemoryError: Java heap space
        内存溢出的错误,创建的数组太大了,超出了给JVM分配的内存
        必须修改代码,创建的数组小一点
         */
    }
}

2、异常的产生过程解析

package exception2;

/**
 * created by apple on 2020/6/21
 * 异常产生过程的解析,分析异常怎么产生,如何处理异常
 */
public class Demo02Exceptoin {
    public static void main(String[] args) {
        //创建int类型的数组,并赋值
        int[] arr = {1,2,3};
        int e = getElement(arr,3); 
        System.out.println(e); //ArrayIndexOutOfBoundsException
    }
    /*
    定义一个方法,获取数组指定索引处的元素
     */
    public static int getElement(int[] arr,int index){
        int ele = arr[index];
        return ele;
    }
}
image.png

异常的处理

Java异常处理的五个关键字:try、catch、finally、throw、throws

3、抛出异常throw

throw小结
throw用在方法内,后面接一个异常对象,使用格式为throw new 异常类名(参数);,将这个异常对象传递到调用者处,并结束当前方法的执行。

throw使用的格式如下:

throw new NullPointerException("要访问的arr数组不存在");

throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围");

使用throw的实例使用:

package exception2;

/**
 * created by apple on 2020/6/21
 * throw
 * 作用:
 *    可以使用throw关键字在指定的方法中抛出指定的异常
 * 使用格式:
 *    throw new xxxException("异常产生的原因");
 * 注意事项:
 *    1、throw 关键字必须写在方法的内部
 *    2、throw 关键字 new的对象必须是Exception或Exception子类对象
 *    3、throw 关键字 抛出指定的异常对象,我们必须处理这个异常对象
 *           a.  throw关键字后边创建的是RuntimeException 或者RuntimeException的子类对象,我们可以不处理,默认交给JVM处理,打印异常对象,中断程序
 *           b.  throw关键字后边创建的是编译异常(写代码的时候报错)就必须处理这个异常,要么throws,要么try catch
 */
public class Demo03Throw {
    public static void main(String[] args) {
       // int[] arr = null;
        int[] arr = new int[3];
        int e = getElement(arr,7);
    }
    /*
   定义一个方法,获取数组指定索引处的元素
        参数:
         int[] arr
         int index
   以后在工作中,我们首先必须对方法中传递过来的参数进行合法性校验,如果参数不合法,我们必须用抛出异常的方式,告诉方法的调用者,传递的参数有问题。
    注意:
        NullPointerException是一个运行期异常,我们不用处理,默认交给JVM处理
        ArrayIndexOutOfBoundsException是一个运行期异常,我们不用处理,默认交给JVM处理
    */
    public static int getElement(int[] arr,int index){
      /*
      我们可以对传递过来的参数数组,进行合法性校验,如果数组arr的值是null,那么抛出空指针异常,告知方法的调用者,传递的数组的值是空
       */
        if ( arr == null){
            throw new NullPointerException("传递的数组的值是空");
        }
        /*
        可以对index进行合法性校验。
        如果index的范围不在数组索引范围内,
        那我们就抛出数组索引越界异常,告知方法的调用者,"传递的索引超出数组索引使用范围"
         */
        if (index < 0 || index > arr.length - 1){
            throw new ArrayIndexOutOfBoundsException("数组索引越界");
        }
        int ele = arr[index];
        return ele;
    }
}

再来看看不使用throw的实例使用的运行:

public static void main(String[] args) {
        //创建一个数组
        int[] arr = {2,4,52,2};
        //根据索引找对应的元素
        int index = 4; //注意索引4已经越界了
        int ele=arr[index];

        System.out.println(ele);
        System.out.println("over");
}

运行结果



这样一对比throw的优势就不言而喻了~

3.2、Objects非空判断_requireNonNul

package exception2;

import java.util.Objects;

/**
 * created by apple on 2020/6/21
 * Objects类中的静态方法 requireNonNull
 * pubic static<T> T requireNonNull(T obj):查看指定引用对象不是null
 *
 */
public class Demo04Objects {
    public static void main(String[] args) {
        method(null);
    }
    public static void method(Object obj){
        //对传递过来的参数进行合法性判断,判断是否为null
        /*if (obj == null){
            throw new NullPointerException("传递的对象的值是null");
        }*/
        //简化代码
        Objects.requireNonNull(obj);
        Objects.requireNonNull(obj,"传递的对象的值是null");
    }
}

声明异常throws

如果产生了问题,我们就会throw将问题描述类即异常进行抛出,也就是将问题返回给该方法的调用者。那么对于调用者来说,该怎么处理呢?一种是进行捕获处理,另一种就是继续讲问题声明出去,使用throws声明处理。
声明异常:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过throws进行声明,让调用者去处理。

throws小结
关键字throws运用于方法声明之上,throws格式为修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2…{ },用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).

4、throws关键字_异常处理的第一种方法

package exception2;

import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * created by apple on 2020/6/21
 * throws异常处理的第一种方式,交给别人处理
 * 作用:
      当方法内部抛出异常对象时,我们必须处理这个异常对象
      可以使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理,自己不处理,别人处理,最终给JVM处理-->中断处理
 * 使用格式:在方法声明时使用
        修饰符 返回值类型 方法名(参数列表) throws  AException,  BException{
            throw new AException("原因");
            throw new BException("原因");
      }
 * 注意事项:
         1、throws必须写在方法声明处
         2、throws声明的异常必须是Exceptin或者Exception的子类
         3、方法内部如果抛出多个异常对象,throws后面也必须声明多个异常, 如果抛出的多个异常对象,有父子类关系,那么直接声明父类异常即可
         4、调用了一个声明抛出异常的方法,必须处理声明的异常, 要么继续使用throws声明抛出 ,交给方法的调用者处理,最终给JVM, 中断处理, 要么try catch 自己处理异常
 */
public class Demo05throws {
    public static void main(String[] args) throws IOException {
        read("c:\\a.txt");
    }
    /*
    定义一个方法,对传递的文件路径进行合法性判断,如果路径不是"c:\\a.txt",抛出文件找不到异常对象,告知方法调用者
    注意:FileNotFoundException是编译异常,抛出了编译异常,必须处理这个异常,可以使用throws继续声明抛出FileNotFoundException 对象,让方法的调用者处理

     */
    public static void read(String filename) throws IOException {
        if (!filename.equals("c:\\a.txt")){
            throw new FileNotFoundException("传递的文件路径不对");
        }
        System.out.println("路径没有问题,读取文件");
        if (!filename.endsWith("a.txt")){
            throw new IOException("文件的后缀名不对");
        }
    }
}

throw 和 throws 的区别小结

throw:

1、表示方法内抛出某种异常对象
2、如果异常对象是非 RuntimeException 则需要在方法申明时加上该异常的抛出 即需要加上 throws 语句 或者 在方法体内 try catch 处理该异常,否则编译报错
3、执行到 throw 语句则后面的语句块不再执行

throws:

1、方法的定义上使用 throws 表示这个方法可能抛出某种异常
2、需要由方法的调用者进行异常处理

5、try...catch_捕获异常,异常处理的第二种方式

如果异常出现的话,会立刻终止程序,所以我们得处理异常:

1、该方法不处理,而是声明抛出,由该方法的调用者来处理(throws)。
2、在方法中使用try-catch的语句块来处理异常。
try-catch的方式就是捕获异常。

捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理。

package exception2;

import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * created by apple on 2020/6/21
 * try  catch  异常处理的第二种方式,自己处理异常
 * try{
 *     可能产生异常的代码
 * }catch(定义一个异常的变量,用来接收try 中抛出的异常){
 *     异常的处理逻辑,产生异常对象后,怎么处理对象。
 *     一般在工作中,会把异常的信息记录在日志中。
 * }
 * ...
 * catch(异常类名 变量名){
 *
 * }
 * 注意:
    1、try中有多个异常对象,可以使用多个catch处理这些异常对象
    2、如果try中产生异常,会执行catch中的异常处理逻辑,执行完catch中的处理逻辑,继续执行try..catch之后的代码,
       如果try中没有产生异常,不会执行catch中异常处理逻辑,执行完try中的代码,继续执行try。。catch之后的代码
 */
public class Demo06try {
    public static void main(String[] args) {
        try {
            //可能产生异常的代码,
            read("d://a.tt");  //输出:catch 传递的文件后缀不是。txt
            // 后续代码
        }catch (IOException e){  //try中抛出什么异常对象,catch就定义什么异常变量。用来接收异常对象
            e.getStackTrace();
            System.out.println("catch 传递的文件后缀不是.txt");
        }
        System.out.println("后续代码");
    }
    public static void read(String filename) throws IOException {

        if (!filename.endsWith(".txt")){
            throw new IOException("文件的后缀名不对");
        }
        System.out.println("文件名没有问题,读取文件");

    }
}

输出:
catch 传递的文件后缀不是。txt
后续代码

6、Throwable类中3个异常处理的方法

1、String getMessage(), 返回此throwable的简短描述
2、String getString(), 返回此throwable的详细消息字符串
3、void printStackTrace(), Jvm打印异常对象,默认此方法,打印异常信息最全面

package exception2;

import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * created by apple on 2020/6/21
 * try  catch  异常处理的第二种方式,自己处理异常
 * try{
 *     可能产生异常的代码
 * }catch(定义一个异常的变量,接收try 中抛出的异常){
 *     异常的处理逻辑,产生异常对象后,怎么处理对象。
 *     一般在工作中,会把异常的信息记录在日志中。
 * }
 * ...
 * catch(异常类名 变量名){
 *
 * }
 * 注意:
 * 1、try中有多个异常对象,可以使用多个catch
 * 2、如果try中产生异常,h会执行catch中的异常处理逻辑
 * 执行完catch中的处理逻辑,继续执行try。。catch之后的带,啊
 * 如果try中没有产生异常,不会执行catch中异常处理逻辑,执行完try中的代码
 * 继续执行try。。catch之后的代码
 */
public class Demo06try {
    public static void main(String[] args) {
        try {
            //可能产生异常的代码,
            read("d://a.tt");  //输出:catch 传递的文件后缀不是。txt
            // 后续代码
        }catch (IOException e){  //try中抛出什么异常对象,catch就定义什么异常变量。用来接收异常对象
            System.out.println(e.getMessage());  //简短信息  :文件的后缀名不对
            System.out.println(e.toString());  //详细信息:重写Objects类的toString ,  java.io.IOException: 文件的后缀名不对
            System.out.println(e);   //默认调用toString方法  java.io.IOException: 文件的后缀名不对
            e.printStackTrace();  //最全面
            /*
            java.io.IOException: 文件的后缀名不对
    at exception2.Demo06try.read(Demo06try.java:45)
    at exception2.Demo06try.main(Demo06try.java:30)
             */
            e.getStackTrace();
            System.out.println("catch 传递的文件后缀不是。txt");
        }
        System.out.println("后续代码");
    }
    public static void read(String filename) throws IOException {

        if (!filename.endsWith(".txt")){
            throw new IOException("文件的后缀名不对");
        }
        System.out.println("文件名没有问题,读取文件");

    }
}

输出:
文件的后缀名不对
java.io.IOException: 文件的后缀名不对
java.io.IOException: 文件的后缀名不对
catch 传递的文件后缀不是。txt
后续代码
java.io.IOException: 文件的后缀名不对
    at exception2.Demo06try.read(Demo06try.java:45)
    at exception2.Demo06try.main(Demo06try.java:30)

7、finally代码块

有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。

try 中有异常,就会给catch处理,导致,try后面的代码执行不到。

格式:

try{
    可能产生异常的代码
}catch(定义一个异常的变量,用来接收try 中抛出的异常){
     异常的处理逻辑,产生异常对象后,怎么处理对象。
     一般在工作中,会把异常的信息记录在日志中。
}
  ...
 catch(异常类名 变量名){ 
}finally{
  无论是否出现异常都会执行
}

注意:
1、 finally不能单独使用,必须和try一起使用
2、finally 一般用于资源释放,无论是否出现异常,最后都要资源释放(IO)

8、异常的注意事项:多异常的捕获处理

1、多个异常分别处理
2、多个异常一次捕获,多次处理,
一个try 多个catch注意事项: catch里面定义的异常变量,如果有父子类关系,那么子类的异常变量必须写在上边,否则会报错,如下图所示:


image.png 父子类异常书序

3、多个异常一次捕获,一次处理,


一次处理异常Exception

总结:
1、运行时异常被抛出可以不处理,既不捕获也不声明抛出
2、如果finally有return语句,永远返回finally中的结果,避免该情况
3、如果父类抛出多个异常,子类重写父类方法时,抛出和父类相同的异常或者父类异常的子类或者不抛出异常
4、父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常,此时子类产生该异常,只能捕获处理,不能声明抛出
5、try catch 后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收

9、finally代码块与return语句

2、如果finally有return语句,永远返回finally中的结果,避免该情况

10、异常注意事项_子父类异常

f父类什么样,子类什么样

package exception2;

/**
 * created by apple on 2020/6/21
 * 字符类的异常
 * 父类异常是什么样,子类也是什么样
 */
public class Fu {
    public void show() throws NullPointerException,ClassNotFoundException{}
    public void show02() throws IndexOutOfBoundsException{}
    public void show03() throws IndexOutOfBoundsException{}
    public void show04(){}
}
class Zi extends Fu{
    //子类重写父类方法时 ,抛出和父类相同的异常
    public void show() throws NullPointerException,ClassNotFoundException{}
    //子类重写父类方法时,抛出父类异常的子类
    public void show02() throws ArrayIndexOutOfBoundsException{}
    //子类重写父类方法时,可以不抛出异常
    public void show03(){}
    //父类方法没有抛出异常,子类重写时,不能抛出异常
    //public void show04(){}
    //子类产生异常,只能捕获处理,不能声明抛出
    public void show04() /*throws Exception */{
        try {
            throw  new Exception("编译期异常");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

11、自定义异常

相关文章

  • 五 异常与多线程——第一节 异常

    1、异常概念&异常体系 Throwable 类是所有异常exception和错误error的超类,在java.la...

  • Java多线程: 如何捕获多线程中的异常

    你处理过多线程中异常吗?如何捕获多线程中发生的异常?捕获子线程的异常与捕获当前线程的异常一样简单吗? 除了try ...

  • 异常与多线程

    1、异常概念&异常体系 Throwable 是所有异常的错误的超类Exception 编译期异常,进行编译jav...

  • Android 学习流程

    1、java * 基础语法 * 面向对象 * 集合 * 多线程 * 异常 异常机制原理 自定义异常 * 输入、输出...

  • 2019-01-20

    异常处理,自定义注册异常,多线程基础知识整理 1.异常 1.1异常的概念 异常:在程序编译完成和执行程序过程中,出...

  • 多线程,异常

    1.实现方式:继承Thread或实现Runable重写run()。 任务写在run()中,要实现线程行为,需要显示...

  • Java 基础:异常

    目录:一、 异常继承体系二、 发生异常到时候,程序的执行特征:三、 异常与错误的区别四、 抛出异常 throw五、...

  • 8. Java 基础:异常

    目录: 一、 异常继承体系二、 发生异常到时候,程序的执行特征:三、 异常与错误的区别四、 抛出异常 throw五...

  • 第一章 何谓心理正常或异常?异常心理学课堂笔记

    第一节正常与异常的标准 一、判定异常心理的标准 标准一: 1. 自己主观痛苦Agony 2. 适应不良Malada...

  • 多线程异常捕获与处理

    线程与异常 每一个Java应用程序都是一个进程,在进程中会启动多个线程来执行各类任务。因为Java线程的本质,所以...

网友评论

      本文标题:五 异常与多线程——第一节 异常

      本文链接:https://www.haomeiwen.com/subject/orgiyrtx.html