异常介绍(笔记)

1异常介绍
在这里插入图片描述
2异常体系和分类
在这里插入图片描述
常见的运行期异常:

NullPointerException:空指针异常,一般是使用null调用了方法,访问属性导致
IndexOutOfBoundsException:索引越界异常(集合会报),超出了集合索引的使用范围
StringIndexOutOfBoundsException:字符串索引越界异常,超出了字符串索引的使用范围
ArrayIndexOutOfBoundsException:数组索引越界异常,超出了数组索引的使用范围
ClassCastException:类型转换异常 向下转型的时候会抛出
ConcurrentModificationException:迭代器并发修改异常 迭代器|增强for遍历集合同时修改集合长度会报
NoSuchElementException:没有元素异常
NumberFormatException:数字格式化异常
IllegalThreadStateException:非法状态异常 线程对象重复的调用start方法

package com.itheima.demo01Exception;

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

/*
    异常的体系和分类
 */
public class Demo01 {
    public static void main(String[] args) {
        //java.lang.Exception extends Throwable类:编译期异常,在写代码的时候,程序报的异常
        /*try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date = sdf.parse("2022-324");
            System.out.println(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }*/

        //java.lang.RuntimeException extends Exception:运行期(时)异常,在运行代码的时候,程序报的异常
        /*try {
            int[] arr = {10,20,30};
            System.out.println(arr[3]);
        } catch (Exception e) {
            e.printStackTrace();
        }*/

        /*
            -- java.lang.Error extends Throwable类 :错误
            OutOfMemoryError: Java heap space:内存溢出的错误
            创建的数组太大了,超出了内存的使用范围(内存装不下了)
         */
        //int[] arr = new int[1000*1000*1000];
        int[] arr = new int[1000*1000];

        System.out.println("后边还有100行代码要执行!");
    }
}

3.异常的产生过程解析(面试)
在这里插入图片描述
4.throw关键字(重点)

throw关键字使用
作用:
让我们在[方法中]抛出指定的异常对象
没有使用throw关键字,程序执行的过程中出现了异常,JVM会创建异常相关的对象,并抛出异常对象
格式:
修饰符 返回值类型 方法名(参数列表){
throw new xxxException(“异常的错误信息”);

throw new yyyException(“异常的错误信息”);
}
注意:
1.throw关键字必须写在[方法中]
2.throw关键字后边创建的对象,必须是Exception或者RuntimeException或者他们的子类
不能是和异常无关的对象(Person,Student==>错误)
3.throw关键字抛出的是运行时(期)异常,我们无需处理异常,默认交给JVM处理(中断)
throw关键字抛出的是编译期异常,我们就必须的处理这个异常

package com.itheima.demo01Exception;

/*
    throw关键字使用
    作用:
        让我们在[方法中]抛出指定的异常对象
        没有使用throw关键字,程序执行的过程中出现了异常,JVM会创建异常相关的对象,并抛出异常对象
 */
public class Demo03throw {
    public static void main(String[] args) {
        //int[] arr = null;
        int[] arr = {10,20,30};
        int element = getElement(arr, 3);
        System.out.println(element);
    }

    /*
        定义一个方法,获取数组指定索引处的元素并返回
        在工作中一般都会对方法传递的实际参数做一些合法性的校验
            参数合法,在使用参数
            参数不合法,就可以使用抛出异常的方式,告之方法的调用者,参数有问题
     */
    public static int getElement(int[] arr,int index){
        /*
            对参数int[] arr进行一个非空判断
            如果数组arr的值null,那么我们就抛出一个空指针异常
            告之方法的调用者,传递的数组arr的值是null
         */
        if(arr==null){
            throw new NullPointerException("您传递的数组arr的值是null");
        }

        /*
            对参数int index数组索引,进行一个校验,判断index是否在数组索引范围内
            如果index不在数组索引的范围内,那么我们就抛数组索引越界异常
            告之方法的调用者,传递的数组的索引超出了范围
         */
        if(index<0 ||index>arr.length-1){
            throw new ArrayIndexOutOfBoundsException("您传递的数组索引["+index+"]超出了数组索引的范围");
        }

        int e = arr[index];
        return e;
    }
}

5.throws关键字(重点)
在这里插入图片描述

package com.itheima.demo01Exception;

/*
    throws关键字使用
    异常处理的第一种方式
    作用:
        throw关键字抛出的是编译期异常,我们就必须的处理这个异常
        可以使用throws关键字把异常对象抛出给方法的调用者处理,最终可以抛出给JVM处理(中断)
    弊端:
        最终会把异常对象抛出给JVM,JVM会中断我们当前正在执行的程序
        那么异常之后代码代码就不会执行了
 */
public class Demo04throws {
    /*
        main(String[] args) throws Exception main方法继续把异常对象Exception抛出给JVM处理
     */
    public static void main(String[] args) throws Exception {
        //int[] arr = null;
        int[] arr = {10,20,30};
        int element = getElement(arr, 3);
        System.out.println(element);
        System.out.println("后续100行代码");
    }

    /*
        定义一个方法,获取数组指定索引处的元素并返回
        getElement(int[] arr,int index) throws Exception 把异常对象Exception抛出给main方法处理
     */
    public static int getElement(int[] arr,int index) throws Exception{
        /*
            对参数int[] arr进行一个非空判断
            如果数组arr的值null,那么我们就抛出一个空指针异常
            告之方法的调用者,传递的数组arr的值是null
         */
        if(arr==null){
            throw new Exception("您传递的数组arr的值是null");
        }

        /*
            对参数int index数组索引,进行一个校验,判断index是否在数组索引范围内
            如果index不在数组索引的范围内,那么我们就抛数组索引越界异常
            告之方法的调用者,传递的数组的索引超出了范围
         */
        if(index<0 ||index>arr.length-1){
            throw new Exception("您传递的数组索引["+index+"]超出了数组索引的范围");
        }

        int e = arr[index];
        return e;
    }
}

6.throws抛出子父类异常的处理(重点)

在方法内部抛出了多个异常对象,有子父类关系,在方法上声明父类异常即可

package com.itheima.demo01Exception;

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

/*
    在方法中抛出的多个异常对象,有子父类关系,在方法上声明父类异常对象即可
    public class FileNotFoundException extends IOException extends Exception
    main(String[] args) throws FileNotFoundException,IOException
    简化为:
        main(String[] args) throws IOException
        main(String[] args) throws Exception
 */
public class Demo05throws {
    /*
        main(String[] args) throws FileNotFoundException,IOException 把两个异常对象甩给JVM处理
     */
    public static void main(String[] args) throws Exception{
        //readFile(null);
        readFile("c:\\hello.java");
    }

    /*
        定义一个方法,方法的参数传递一个文件的路径 d:\\abc.java
        在方法中根据文件的路径,读取文件中的内容(IO流)
        readFile(String path)throws FileNotFoundException,IOException 把两个异常对象甩给main方法处理
     */
    public static void readFile(String path)throws FileNotFoundException,IOException{
        /*
            对文件的路径path进行合法性校验,判断path是否为null
            IOException:读写异常
         */
        if(path==null){
            throw new IOException("传递的文件的路径是null");
        }

        /*
            对文件的路径path进行合法性校验,判断path是否为d:\\abc.java
            FileNotFoundException:文件找不到异常
         */
        if(!path.equals("d:\\abc.java")){
           throw new FileNotFoundException("传递的文件的路径不是d:\\abc.java");
        }

        //路径没有问题,读取文件
        System.out.println("读取到了d:\\abc.java文件,文件中的内容是abc");
    }
}

7.try…catch关键字(重点)

快捷键 选择中代码==>ctrl+alt+T==>选择try catch
在这里插入图片描述

package com.itheima.demo01Exception;

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

/*
    try…catch异常处理
    异常处理的第二种方式
    作用
        1.throw关键字抛出的是编译期异常,我们就必须的处理这个异常
        2.调用了一个声明抛出编译期异常的方法,我们就必须的处理这个异常
        就可以使用try catch关键字自己手动处理异常
    好处:
	    使用try catch处理异常,可以继续执行try catch后边的代码
    注意:
        1.try中产生了异常对象,那么就会执行catch中异常的处理逻辑,执行完毕会继续执行try catch之后的代码
        2.try中没有产生异常对象,那么就不会执行catch中异常的处理逻辑,执行完try中的代码,会继续执行try catch之后的代码
    快捷键 选择中代码==>ctrl+alt+T==>选择try catch
    try:捕获
    catch:接住
 */
public class Demo06tryCatch {
    public static void main(String[] args) {
        try {
            //可能会产生异常的代码
            readFile("d:\\abc.java");
        } catch (FileNotFoundException e) {//FileNotFoundException e = new FileNotFoundException("传递的文件的路径不是d:\\abc.java");
            //异常的处理逻辑:可以随意编写
            System.out.println("哈哈");
        }catch (IOException e) {//IOException e= new IOException("传递的文件的路径是null");
            System.out.println("呵呵");
        }
        System.out.println("后续100行代码!");
    }


    public static void readFile(String path)throws FileNotFoundException,IOException {
        if(path==null){
            throw new IOException("传递的文件的路径是null");
        }

        if(!path.equals("d:\\abc.java")){
            throw new FileNotFoundException("传递的文件的路径不是d:\\abc.java");
        }

        //路径没有问题,读取文件
        System.out.println("读取到了d:\\abc.java文件,文件中的内容是abc");
    }
}

8.Throwable类中定义的异常处理逻辑(了解)

Throwable类中定义的异常处理逻辑(了解)
java.lang.Throwable:异常和错误的父类,里边定义的方法所有的异常类都可以使用
String getMessage​() 返回此可抛出的简短描述。
String toString​() 重写Object类toString方法,返回此throwable的详细消息字符串。
void printStackTrace​() JVM在控制台打印异常信息,默认调用的方法,打印异常信息最全面的
以上3个异常的处理方法,我们可以使用,也可以自定义异常的处理逻辑

Throwable类是Exception的父类

package com.itheima.demo01Exception;

/*
    Throwable类中定义的异常处理逻辑(了解)
    java.lang.Throwable:异常和错误的父类,里边定义的方法所有的异常类都可以使用
        String getMessage​() 返回此可抛出的简短描述。
        String toString​()  重写Object类toString方法,返回此throwable的详细消息字符串。
        void printStackTrace​() JVM在控制台打印异常信息,默认调用的方法,打印异常信息最全面的
    以上3个异常的处理方法,我们可以使用,也可以自定义异常的处理逻辑
 */
public class Demo07Throwable {
    public static void main(String[] args){
        try {
            throw new Exception("异常了");
        } catch (Exception e) {//Exception e = new Exception("异常了");
            //String getMessage​() 返回此可抛出的简短描述。
            String message = e.getMessage();
            System.out.println(message);//异常了

            //String toString​()  重写Object类toString方法,返回此throwable的详细消息字符串。
            String s = e.toString();
            System.out.println(s);//java.lang.Exception: 异常了
            System.out.println(e);//java.lang.Exception: 异常了

            /*
                void printStackTrace​() JVM在控制台打印异常信息,默认调用的方法,打印异常信息最全面的
                java.lang.Exception: 异常了
	            at com.itheima.demo01Exception.Demo07Throwable.main(Demo07Throwable.java:14)
             */
            e.printStackTrace();

            //以上3种打印异常信息的方法,都不使用,自定义异常的处理逻辑
            System.out.println("哈哈终于出现了异常了"+e);//哈哈终于出现了异常了java.lang.Exception: 异常了
        }
        System.out.println("后续代码!");
    }
}

9.finally关键字(重点)

finally关键字里边定义的代码,无论程序是否有异常,都会执行

finally必须和try一起使用
在这里插入图片描述

package com.itheima.demo01Exception;

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

/*
    finally代码块
    格式:
        try {
            【A】可能会出现异常的代码
        } catch(定义一个异常相关的变量) {
            【B】出现异常后执行的代码(异常的处理逻辑)
        } finally {
            【C】一定会执行的代码(释放资源)
        }

    finally代码块的特点:
        finally代码块的内容无论程序是否出现异常都会执行。
 */
public class Demo08finally {
    public static void main(String[] args) throws ParseException {
        /*
            程序执行流程:
            1.没有异常: A C D
            2.有异常:   B C D
         */
        /*try {
            //【A】可能会出现异常的代码
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date = sdf.parse("2022-324");
            System.out.println("[A]:"+date);
        } catch (ParseException e) {
            //【B】出现异常后执行的代码(异常的处理逻辑)
            System.out.println("[B]:"+e.toString());
        } finally {
            //【C】一定会执行的代码(释放资源)
            System.out.println("[C]:无论程序是否出现异常,都会执行");
        }*/

        /*
            程序执行流程:
            1.没有异常: A C D
            2.有异常:   C JVM终止程序
         */
        try {
            //【A】可能会出现异常的代码
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date = sdf.parse("2022-324");
            System.out.println("[A]:"+date);
        }  finally {
            //【C】一定会执行的代码(释放资源)
            System.out.println("[C]:无论程序是否出现异常,都会执行");
        }

        System.out.println("[D]:后续代码!");
    }
}

10.异常处理的注意事项(了解)

1).运行时(期)异常:运行程序之后出现的异常

异常处理的注意事项:
1.运行时(期)异常被抛出可以不处理。
即不捕获(不使用try…catch来捕获处理异常)
也不声明抛出(不使用throws声明抛出异常对象)。
运行时异常,我们无需处理,默认会交给JVM处理==>中断
运行时异常,我们处理没有意义,处理了也是为了让后续代码能继续执行
但是运行时异常本身还是存在的:使用数组索引超出了数组索引的范围,
就算我们使用try…catch处理这个异常实际上数组还是越界的,
没有从根本上解决问题这时候我们应该修改代码,不让数组越界

package com.itheima.demo02Exception;

/*
    运行时(期)异常:运行程序之后出现的异常
 */
public class Demo01Exception {
    public static void main(String[] args) {
        /*try {
            int[] arr = {10,20,30};
            System.out.println(arr[3]);
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        //就算我们使用try...catch处理这个异常实际上数组还是越界的

        //在工作中:运行期异常我们必须的修改代码,不让运行期异常出现,从根本上解决问题
        int[] arr = {10,20,30};
        System.out.println(arr[1]);

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

2).子父类异常的处理

异常处理的注意事项:
2.子父类异常的处理
a.如果父类的方法抛出了多个异常,
子类重写父类方法时,子类可以抛出和父类方法相同的异常
子类重写父类方法时,抛出父类异常的子类
子类重写父类方法时,可以不抛出异常
b.父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。
此时子类方法中产生异常,只能捕获处理,不能声明抛出
注意:
子类重写父类的方法,父类方法异常什么样,子类和父类一样就可以了,无序考虑异常问题
爹抛儿子也抛
爹没抛儿子也不抛

package com.itheima.demo02Exception;

public class Demo02Fu {
    public void show01() throws NullPointerException,IndexOutOfBoundsException{}

    public void show02() throws IndexOutOfBoundsException{}

    public void show03() throws Exception{}

    public void show04(){}
}
package com.itheima.demo02Exception;

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

public class Demo03Zi extends Demo02Fu {
    //子类重写父类方法时,子类可以抛出和父类方法相同的异常
    @Override
    public void show01() throws NullPointerException, IndexOutOfBoundsException { }

    /*
        子类重写父类方法时,抛出父类异常的子类
        ArrayIndexOutOfBoundsException:数组索引越界异常 extends IndexOutOfBoundsException:索引越界异常
        StringIndexOutOfBoundsException:数组索引越界异常 extends IndexOutOfBoundsException:索引越界异常
     */
    @Override
    //public void show02() throws ArrayIndexOutOfBoundsException { }
    public void show02() throws StringIndexOutOfBoundsException { }

    //子类重写父类方法时,可以不抛出异常
    @Override
    public void show03() { }

    //父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常
    //overridden method does not throw 'java.lang.Exception'
    /*@Override
    public void show04()throws Exception { }*/

    //此时子类方法中产生异常,只能捕获处理,不能声明抛出
    @Override
    public void show04() {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date = sdf.parse("2022-324");
            System.out.println("[A]:"+date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

11.自定义异常(使用)

1).概述和基本定义格式

自定义异常:
java给我们提供异常类,不够我们使用,就需要自己定义一些异常相关的类
注意:
1.自定义异常的类名,一般都是以Exception结尾,说明这个类就是一个异常相关的类(见名知意)
2.自定义异常类
a.可以继承Exception:自定义异常就是一个编译期异常
使用:如果在方法中抛出了编译期异常,那么我们就必须处理这个异常,有两种处理方式
1).使用throws关键字在方法上声明抛出这个异常对象,让方法的调用者处理,最终抛出给JVM(中断)
2).使用try…catch自己捕获处理这个异常对象
b.也可以继承RuntimeException:自定义异常就是一个运行期异常
使用:如果在方法中抛出了运行期异常,我们无需处理,默认交给JVM处理(中断)
自定义异常的格式:
public class xxxException extends Exception|RuntimeException{
//定义一个空参数的构造方法
public xxxException(){
super();//调用父类的空参数构造方法
}
//定义一个带异常信息的构造方法
//我们查询异常相关的源码发现,java每个异常类都会定义一个带异常信息的构造方法,把异常信息传递给父类处理
public xxxException(String message){
super(message);//调用父类的空参数构造方法
}
}

2).自定义异常的使用

a.自定义异常类是编译异常

package com.itheima.demo03myException;

//自定义异常类是一个编译期异常
public class RegisterException extends Exception{
    public RegisterException() {
    }

    public RegisterException(String message) {
        super(message);
    }
}
package com.itheima.demo03myException;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

/*
    注册的案例:
    1.定义一个集合,存储用户已经注册过的用户名
    2.使用Scanner获取用户本次输入的用户名
    3.定义一个方法,在方法中判断用户名是否已经被注册
        a.遍历集合获取每一个已经注册过的用户名
        b.使用用户本次输入的用户名和遍历得到的用户名比较
        c.一致,已经注册过了,抛出RegisterException异常,告之用户您输入的用户名已经被注册了
        d.循环结束了,还没有相同的用户名,把用户名存储到集合中
        e.给用户提示"恭喜您注册成功!"
 */
public class Demo01 {
    public static void main(String[] args) throws RegisterException {
        //1.定义一个集合,存储用户已经注册过的用户名
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"jack","rose","汤姆","杰瑞");
        //2.使用Scanner获取用户本次输入的用户名
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您要注册的用户名:");
        String name = sc.next();
        //调用校验的方法
        checkName(list,name);
    }

    //3.定义一个方法,在方法中判断用户名是否已经被注册
    public static void checkName(ArrayList<String> list,String name) throws RegisterException {
        //a.遍历集合获取每一个已经注册过的用户名
        for (String n : list) {
            //b.使用用户本次输入的用户名和遍历得到的用户名比较
            if(name.equals(n)){
                //c.一致,已经注册过了,抛出RegisterException异常,告之用户您输入的用户名已经被注册了
                //RegisterException是一个编译期异常,我们抛出异常之后,必须处理异常
                throw new RegisterException("您输入的用户名["+name+"]已经被注册了!");
            }
        }
        //d.循环结束了,还没有相同的用户名,把用户名存储到集合中
        list.add(name);
        System.out.println(list);
        //e.给用户提示"恭喜您注册成功!"
        System.out.println("恭喜您注册成功!");
    }
}

b.自定义异常是运行期异常

package com.itheima.demo04Exception;

//自定义异常类是一个运行期异常
public class RegisterException extends RuntimeException{
    public RegisterException() {
    }

    public RegisterException(String message) {
        super(message);
    }
}
package com.itheima.demo04Exception;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

/*
    注册的案例:
    1.定义一个集合,存储用户已经注册过的用户名
    2.使用Scanner获取用户本次输入的用户名
    3.定义一个方法,在方法中判断用户名是否已经被注册
        a.遍历集合获取每一个已经注册过的用户名
        b.使用用户本次输入的用户名和遍历得到的用户名比较
        c.一致,已经注册过了,抛出RegisterException异常,告之用户您输入的用户名已经被注册了
        d.循环结束了,还没有相同的用户名,把用户名存储到集合中
        e.给用户提示"恭喜您注册成功!"
 */
public class Demo01 {
    public static void main(String[] args)  {
        //1.定义一个集合,存储用户已经注册过的用户名
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"jack","rose","汤姆","杰瑞");
        //2.使用Scanner获取用户本次输入的用户名
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您要注册的用户名:");
        String name = sc.next();
        //调用校验的方法
        checkName(list,name);
    }

    //3.定义一个方法,在方法中判断用户名是否已经被注册
    public static void checkName(ArrayList<String> list,String name)  {
        //a.遍历集合获取每一个已经注册过的用户名
        for (String n : list) {
            //b.使用用户本次输入的用户名和遍历得到的用户名比较
            if(name.equals(n)){
                //c.一致,已经注册过了,抛出RegisterException异常,告之用户您输入的用户名已经被注册了
                //RegisterException是一个运行期异常,我们抛出异常之后,无需处理,默认交给JVM处理
                throw new RegisterException("您输入的用户名["+name+"]已经被注册了!");
            }
        }
        //d.循环结束了,还没有相同的用户名,把用户名存储到集合中
        list.add(name);
        System.out.println(list);
        //e.给用户提示"恭喜您注册成功!"
        System.out.println("恭喜您注册成功!");
    }
}

异常总结:

我们以后调用了一个抛出异常的方法:有两种处理异常的方式
1.使用throws关键字,把异常对象抛出给方法的调用者处理,最终抛出给JVM(中断)
2.使用try…catch自己手动处理异常,可以执行异常之后的代码

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旭子在努力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值