Java--异常处理try_catch和throws

异常处理try_catch和throws

  • throw关键字
  • Objects非空判断
  • 第一种方式:throws处理异常
  • 第二种方式:try_catch 处理异常
    • Throwable类中3个异常处理的方式
  • finally代码块
  • 多异常处理
  • 自定义异常

throw关键字

package 异常学习;
/*
* java.lang.Throwable:类是java语言中所有错误或异常的超类
*       Excepttion:编译期异常,进行编译Java程序错误
*           RuntimeException:运行期异常,java程序在运行过程中出现的异常
*       Error:错误
*           错误必须通过修改源代码,程序才能继续执行
*
* 异常产生过程解析(分析异常怎么产生的们如何处理异常)
*        方法将异常抛给main方法,main方法将异常抛给JVM
*
* 异常的处理:
*       1.抛出异常throw关键字,可以在指定的方法中抛出指定的异常
*               使用格式:
*                       throw new ***Exception("异常产生的原因");
*               注意事项:
*                   1.throw关键字必须写在方法的内部
*                   2.throw关键字后边new对象必须是Exception或者是Exception的子类对象
*                   3.throw关键字抛出指定的异常对象。我们就必须处理这个异常对象
*                           throw关键字后边创建的是RuntimeException或者是RuntimeException的子类对象,我们可以不处理,默认交给JVM处理(打印异常,中断程序)
*                           throw关键字后边创建的是编译异常(写代码的时候报错),我们就必须处理这个异常,要么throws,要么try...catch...
*
* */
public class Demo01Exception {
    public static void main(String[] args) {
        //创建数组 并赋值
        int[] arr = {1, 2, 3, 4};
//        int[] arr = null;
        int e = getElements(arr, 6);//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
//        System.out.println(e);


    }

    /*
    * 创建一个方法,获取数组指定索引的元素
    * 以后工作中,我们首先对方法传递过来的参数进行合法性校验,
    * 如果参数不合法,纳闷我们就必须使用抛出异常的方式 告知方法的调用者,传递的参数有问题
    *   注意:
    *       异常.NullPointerException: 传递的数组值是空是一个运行期异常,我们不用处理,默认交给JVM处理
    * */
    public static int getElements(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;
    }
}
########################运行结果#################
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 数组的索引越界了
	at 异常学习.Demo01Exception.getElements(Demo01Exception.java:55)
	at 异常学习.Demo01Exception.main(Demo01Exception.java:29)

Objects非空判断

package 异常学习;

import java.util.Objects;

/*
* Objects类中的静态方法:
*   public static  T requireNonNull(T obj) :查看指定引用对象不是null
* 源码:
* public static  T requireNonNull(T obj) {
*   if (obj == null)
*       throw new NullPointerException();
*   return obj;
* }
*
* */
public class Demo02Objects {
    public static void main(String[] args) {
        method(null);
    }

    //创建一个方法
    public static void method(Object obj) {
//        //对传递的参数进行合法性判断,判断是否为空
//        if (obj == null) {
//            throw new NullPointerException("传递的对象值是空");
//        }
        //等价于直接调用Objects的非空判断
//        Objects.requireNonNull(obj);
        Objects.requireNonNull(obj, "传递的对象值是空");
    }
}
#####################运行结果#############
Exception in thread "main" java.lang.NullPointerException: 传递的对象值是空
	at java.base/java.util.Objects.requireNonNull(Objects.java:233)
	at 异常学习.Demo02Objects.method(Demo02Objects.java:29)
	at 异常学习.Demo02Objects.main(Demo02Objects.java:18)

第一种方式:throws处理异常

package 异常学习;

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

/*
* throws关键字:异常处理的第一种方式,交给别人处理
* 作用:
*       当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象
*       可以使用throws关键字处理异常对象,会把异常对象声明抛给调用者使用(自己不处理,交给别人处理),最终交给JVM处理,中断处理
* 使用格式:
*       修饰符 返回值类型 方法名(参数列表) throws AAAAException,BBBBException...{
*                       throw new AAAAException("产生的原因"));
*                       throw new BBBBException("产生的原因"));
*                   ....
*                   }
* 注意:
*       1.throws关键字必须写在方法声明处
*       2.throws关键字后边声明的异常必须是Exception或者是Exception的子类
*       3.方法内部如果抛出了多个异常,那么throws关键字后边也必须声明多个异常
*           如果抛出的异常 有子父类关系,那么直接声明父类异常即可
*       4.调用了一个声明抛出异常的方法,我们就必须处理声明的异常
*           要么继续使用throws抛出异常,要么try...catch
* */
public class Demo03Throws {
    public static void main(String[] args) throws IOException {     //调用readFile方法时,也需要继续抛出异常 ,FileNotFoundException是IOException的子类,直接声明父类异常就可以
        readFile("c:\\a.txt");

    }

    //定义一个方法,对传播的文件路径进行合法性判断
    //注意:FileNotFoundException是编译异常,必须处理这个异常
    //可以使用throws继续声明抛出这个异常对象,让方法调用者处理
    public static void readFile(String filename) throws IOException {
        if (!filename.equals("c:\\b.txt")) {
            throw new FileNotFoundException("传递的路径不是c:\\a.txt");
        }
        /*
        * 如果传递的路径不是.txt结尾
        * 抛出后缀名不对的异常
        * */
        if (!filename.endsWith(".txt")) {
            throw new IOException("文件名后缀不对");
        }
        System.out.println("路径没有问题,读取文件");
    }

}
################运行结果#####################
Exception in thread "main" java.io.FileNotFoundException: 传递的路径不是c:\a.txt
	at 异常学习.Demo03Throws.readFile(Demo03Throws.java:36)
	at 异常学习.Demo03Throws.main(Demo03Throws.java:27)

第二种方式:try_catch 处理异常

Throwable类中3个异常处理的方式

package 异常学习;

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

/*
* 异常处理的第二种方式:(自己处理)
*   格式:
*       try{
*           可能产生异常的代码
*       }catch(定义一个异常的变量,用来接收try抛出的异常对象){
*           异常的处理逻辑,一般在工作中,会把异常信息记录到一个日志中
*       }
*       ....
*       catch(异常类型 变量名){
*       }
*
* 注意:
*       1.try中可能出现多个异常对象,那么就可以使用多个catch来处理这些异常
*       2.如果try产生异常。那么就执行catch中的异常处理逻辑,执行完毕catch中的逻辑,继续执行try...catch之后的代码
*          如果try没有产生异常,就不会处理catch中的处理逻辑,直接执行try...catch之后的代码
*
* */
public class Demo04TryCatch {
   public static void main(String[] args) {
       try {
           readFile("d:\\a.tx");
           System.out.println("这里需要使用finally代码块,才能够在有异常的时候读到");

       } catch (IOException e) {      //try抛出什么异常对象,catch就定义什么异常对象,用来接收这个异常对象
//            System.out.println("catch--传递的文件地址后缀不对");

           /*
           * Throwable类中定义了3个异常处理的方法:
           *   	String getMessage()      返回此 throwable 的简短描述
           *        String	toString()       返回此 throwable 的详细描述
           *      void	printStackTrace()    将此 throwable 及其追踪输出至标准错误流
            * */

//            System.out.println(e.getMessage());
           /*运行结果:文件名后缀不对
           * */
//            System.out.println(e.toString());
           /*运行结果:java.io.IOException: 文件名后缀不对
           * */
           e.printStackTrace();
           /*运行结果:java.io.IOException: 文件名后缀不对
           * at 异常学习.Demo04TryCatch.readFile(Demo04TryCatch.java:58)
           * at 异常学习.Demo04TryCatch.main(Demo04TryCatch.java:27)
           * */

       }
       System.out.println("后续代码");

   }
   public static void readFile(String filename) throws IOException {

       /*
        * 如果传递的路径不是.txt结尾
        * 抛出后缀名不对的异常
        * */
       if (!filename.endsWith(".txt")) {
           throw new IOException("文件名后缀不对");
       }
       System.out.println("路径没有问题,读取文件");
   }
}
##########################运行结果################
java.io.IOException: 文件名后缀不对
   at 异常学习.Demo04TryCatch.readFile(Demo04TryCatch.java:63)
   at 异常学习.Demo04TryCatch.main(Demo04TryCatch.java:27)
后续代码

finally代码块

package 异常学习;

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

/*
* finally:有一些特定的代码无论异常是否发生,都需要执行。
* 另外,因为异常会引发程序跳转,导致有些语句执行不到。
* 而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。
*    如果finally有return语句,永远返回finally中的结果,应该避免该情况.
*
* 格式:
*        try{
*           可能产生异常的代码
*       }catch(定义一个异常的变量,用来接收try抛出的异常对象){
*           异常的处理逻辑,一般在工作中,会把异常信息记录到一个日志中
*       }
*       ....
*       catch(异常类型 变量名){
*       }finally{
*           无论是否出现异常都会执行
*       }
*
* 注意:
*   1.finally不饿能单独使用,必须和try一起使用
*   2.finally一般用于资源释放(资源回收),无论程序是否出现异常,最后都要资源释放(IO)
*
* */
public class Demo05finally {
    public static void main(String[] args) {
        try {

            readFile("d:\\a.tx");
        } catch (IOException e) {

            e.printStackTrace();
        }finally {
            //无论是否出现异常都会执行
            System.out.println("资源释放");
        }
    }


    public static void readFile(String filename) throws IOException {

        /*
         * 如果传递的路径不是.txt结尾
         * 抛出后缀名不对的异常
         * */
        if (!filename.endsWith(".txt")) {
            throw new IOException("文件名后缀不对");
        }
        System.out.println("路径没有问题,读取文件");
    }

}
#####################运行结果################
java.io.IOException: 文件名后缀不对
	at 异常学习.Demo05finally.readFile(Demo05finally.java:51)
	at 异常学习.Demo05finally.main(Demo05finally.java:33)
资源释放

多异常处理

package 异常学习;

import java.util.List;

/*
* 多个异常使用捕获又该如何处理呢?
*   1. 多个异常分别处理。
*   2. 多个异常一次捕获,多次处理。
*   3. 多个异常一次捕获一次处理。
*
*       此外:父类是什么异常,子类就是什么异常
* */
public class Demon06多异常处理 {

    public static void main(String[] args) {
        //1. 多个异常分别处理。
        /*try {
            int[] arr = {1, 2, 3};
            System.out.println(arr[3]);
        } catch (ArrayIndexOutOfBoundsException a) {
            a.printStackTrace();
        }

        try {
            List list = List.of(1, 2, 3);
            System.out.println(list.get(3));
        } catch (IndexOutOfBoundsException e) {
            e.printStackTrace();
        }
        System.out.println("后续代码");
        */

        //2.多个异常一次捕获,多次处理。
        /*try {
            int[] arr = {1, 2, 3};
            System.out.println(arr[4]);
            List list = List.of(1, 2, 3);
            System.out.println(list.get(6));

        } catch (ArrayIndexOutOfBoundsException a) {
            a.printStackTrace();
        } catch (IndexOutOfBoundsException e) {      //catch中定义的异常对象,如果有子父类关系,那么子类的异常变量必须写在上面,否则就会报错
            e.printStackTrace();
        }
        */
        //3. 多个异常一次捕获一次处理。
        try {
            int[] arr = {1, 2, 3};

            List<Integer> list = List.of(1, 2, 3);
            System.out.println(list.get(6));
            System.out.println(arr[4]);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
#################运行结果###############
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 3
	at java.base/java.util.ImmutableCollections$ListN.get(ImmutableCollections.java:547)
	at 异常学习.Demon06多异常处理.main(Demon06多异常处理.java:51)

自定义异常

package 异常学习;

/*
 * 自定义异常类:
 *       格式:
 *           public class XXXException extends Exception | RunTimeException{
 *               添加一个空参数的构造方法;
 *               添加一个带异常信息的构造方法;
 *           }
 *       注意:
 *           1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类
 *           2.必须继承Exception(编译异常,必须处理,要么throws要么try..catch) | RunTimeException(运行异常)(无需处理,交给JVM处理)
 * */
public class Demo07自定义异常 extends Exception {
    public Demo07自定义异常() {
        super();
    }
    /*
    * 添加一个带异常信息的构造方法
    * 查看源码都会发现,所有的异常类都会有一个带异常信息的构造方法,方法内部会调用父类带异常信息的构造方法,让父类来处理这个异常信息
    * */

    public Demo07自定义异常(String message) {
        super(message);
    }
}

你可能感兴趣的:(java小知识回顾,java,jvm,mce异常)