异常处理 ?处理(try-catch) :甩锅(throws)_ java异常(Exception)处理

简介: 异常处理 ?处理(try-catch) :甩锅(throws)_ java异常(Exception)处理

本章概要

本章主要和大家一起学习java异常类的处理机制,深入学习java异常类。

掌握异常处理机制,及背后的逻辑。

1.了解异常体系,学习常见的异常类

2.知道如何处理异常,掌握try-catch 或者 throws的使用和区别

3.能够读懂异常代码,知道何处可能会有异常出现


java异常处理入门

二话不说,先看代码!


//异常处理入门
public class Exception1 {
    public static void main(String[] args) {
        int m = 10;
        int n = 0;
        System.out.println(m/n);//分母不能为0 算数异常
        System.out.println("程序继续....");//异常导致程序奔溃并未执行该语句
    }
}

image.png

可以看到当一个代码某个语句出现异常,如果我们不做任何处理,java程序就会奔溃,导致程序中断,后面的语句无法执行!


那如果我们是一个团队在写一个项目,我们有成千上万行代码,如果应因为某一行语句出现异常,而导致整个项目奔溃,显然不合理!


我们可以采取解决方案将异常处理


捕捉异常

对异常进行捕获,保证程序可以继续运行。

用try-catch语句进行捕捉异常,大致细节我们后面讲到,我们先看下面代码:

//try-catch对异常捕捉
public class Exception1 {
    public static void main(String[] args) {
        int m = 10;
        int n = 0;
        try {
            System.out.println(m/n);//分母不能为0 算数异常
        } catch (Exception e) { //捕捉异常
            System.out.println(e.getMessage());//打印异常信息
        }
        System.out.println("程序继续...."); //处理完异常继续执行该语句
    }
}

image.png

我们可以看到捕捉处理异常后程序可以正常执行!


我们再来学习一下try-catch语句在IDEA下的快捷键吧!

1.首先我们选中将会报异常的语句

2.快捷键Ctrl+Alt+T

3.选中要进行的操作

image.png


异常介绍

异常分类

java异常分为两大类:


Error(错误)

java虚拟机无法解决的重大问题,JVM系统内部错误,资源耗尽等严重情况。如:栈溢出StackOverflowError,内存不足out of memory(OOM) 。Error是严重错误,会导致程序奔溃!就好比人得了绝症,没得救!

Exception

由编程错误或其他外界因素导致的一般性问题,可以通过针对性的代码来处理。例如:空指针访问,文件是否存在,数据库连接等等。

Exception又分为两种:

1.受查(编译)异常:在编译器期间,编译器便能够查出的错误!

2.非受查(运行)异常RuntimeException :在运行期间才会报错!

异常体系图

image.png

只是举例了几种常见的异常!

大家可以下去自行查看

异常体系图十分方便体现了继承和实现的关系!

虚线是实现接口,实线是继承父类!

IEDA查看类的关系图步骤:

1.找到一个类选中

2.鼠标右击

3.选择

image.png

4.然后再选择该类,鼠标右击查看,选择你要展现父类或者子类!

image.png

异常体系图的小结

基本概念

java语言中,将程序执行中出现的不正常情况称为“异常”(开发中语法错误和逻辑错误不是异常)


运行时异常

常见的运行时异常包括


NullPointerException 空指针异常

ArithmeticException 数学运算异常

ArrayIndexOutOfBoundsException 数组下标越界异常

ClassCastException 类型转换异常

NumberFormatException 数字格式不正确异常

常见运行时异常举例


NullPointerException 空指针异常

//空指针异常
public class NullPointerException_ {
    public static void main(String[] args) {
        String str = null;
        System.out.println(str.length());//NullPointException
    }
}

image.png

-ArithmeticException 数学运算异常

//数学运算异常
public class ArithmeticException_ {
    public static void main(String[] args) {
        int m = 10;
        int n = 0;
            System.out.println(m/n);//分母不能为0 算数异常
    }
}

image.png

ArrayIndexOutOfBoundsException数组越界异常


//数组下标越界异常
public class ArrayIndexOutOfBoundsException_ {
    public static void main(String[] args) {
        int[] arr = new int[3];
        System.out.println(arr[4]); //arr下标[0,2]
    }
}

image.png

ClassCastException类型转换异常

//类型转换异常
public class ClassCastException_ {
    public static void main(String[] args) {
        String string = "java";
        Object ob = string; //上转型对象
        Integer integer = (Integer)ob; //类型转换异常
    }
}

image.png

-NumberFormatException 数字格式不正确异常


//数字格式不正确异常
public class NumberFormatException_ {
    public static void main(String[] args) {
        int a = Integer.parseInt("1aba");//将字符串转换成整型
                                         //数字格式不正确异常
    }
}

image.png

编译异常

编译异常就是在编译期间就要处理的异常,也叫受查异常,就是说编译器在编译期间会进行检查,不处理该异常,就无法通过编译。

编译异常必须处理!

常见编译异常:

1.SQLException //操作数据库时,查询表可能发生异常

2.IOException //操作文件时,发生的异常

3.FileNotFoundException //当操作一个不存在文件时,发生的异常

4.EOFException//操作文件,文件到末尾,发生的异常

5.IllegalArgumentException//参数异常

编译异常举例

因为bug郭还没有学习到数据库和文件操作。我们就举一个案例来了解一下编译异常!

//操作文件,发生的编译异常
public class IOException_ {
    public static void main(String[] args) {
        File file = new File("D:\\a.txt");
        file.createNewFile();//异常
    }
}

image.png

可以看到编译异常,如果我们不进行处理,代码就无法编译通过!

//try-catch处理异常
public static void main(String[] args) {
        File file = new File("D:\\a.txt");
        //try-catch处理异常  快捷键:Ctrl+Alt+T
        try {
            file.createNewFile();//异常
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }

image.png


异常课堂练习

我们了解了异常,哪来看看下面代码是否会发生异常吧!

//题目一
 public static void main(String[] args) {
        String[] strings = new String[]{"java","bug","2022"};
        System.out.println(strings[3]);
    }

结果:

ArrayIndexOutOfBoundsException数组下标越界异常

image.png

//题目二
public static void main(String[] args) {
        String string = "java";
        Object ob = string; 
        Integer integer = (Integer)ob; 
    }

ClassCastException类型转换异常

//题目三
class Cat{
    public String name;
    Cat(String name){
        this.name = name;
    }
}
public class test_1 {
    public static void main(String[] args) {
        Cat cat= new Cat("豆花");
        cat = null;
        System.out.println(cat.name);
    }
}

image.png

-NullPointerException空指针异常

//题目四
public class Test_1 {
    public static void main(String[] args) {
        int[] array = new int[]{1,3,3,4,5,6};
        array = null;
        for (int x:
             array) {
            System.out.print(x+" ");
        }
    }
}

image.png

异常处理

基本介绍


异常处理就是,当异常发生时,对异常处理的方式!


异常处理方式


try-catch-finally程序员在代码中捕获发生的异常,自行处理

throws将发生的异常交给调用者(方法)来处理,最顶级的处理者就是JVM

try-catch-finally处理方式介绍

//`try-catch-finally异常处理机制介绍
class Exception_1{
    public static void exception_(){
        //异常处理在方法中
        try {//可能出现异常的代码用try包裹
            String str = "try-catch-finally";
            System.out.println("异常语句前面的代码会执行");
            str = null; int len = str.length();//出现异常代码
            //上方语句出现异常后,后面的语句将不会执行,直接到catch
            System.out.println("异常的代码后面的代码不执行");
        } catch (Exception e) {
            //如果异常是catch里中的异常类型或者子类
            //将会捕捉到异常对象e,我们可以通过异常对象得到异常信息...
            System.out.println("catch捕捉到了异常!");
        } finally {
           //不管代码是否被捕捉到异常,finally语句都会被执行
            // finally代码块中的语句一定会执行
        }
        System.out.println("程序继续...");
    }
}

image.png

throws处理方式介绍

//throws机制处理异常方式
public class Test_3 {
    //抛出异常通常定义在 方法头部()后面 throws + 异常类型
    public static void main(String[] args) throws NumberFormatException{
        f1(); 
    }
    public static void f1()throws NumberFormatException{
        f2();//两种选择,处理或者抛出
    }
    public static void f2()throws NumberFormatException{
        f3();//两种选择,处理或者抛出
    }
    public static void f3()throws NumberFormatException{
        f4();//两种选择,处理或者抛出
    }
    public static void f4()throws NumberFormatException{
        throw new NumberFormatException();
        //出现异常,f4可选择try-catch-finally捕捉异常
        // 或者throws抛出给调用者
    }
}

JVM处理后,打印异常信息,退出程序

image.png




throws处理异常方式就是将异常抛出给调用者(方法),每个接收到异常的调用者(方法)都有两种处理异常的方式:1.向上抛给他的调用者 2.try-catch-finally捕获异常如果一直向上抛给调用者,如果最后的调用者main方法也继续抛出,那么最终会由JVM处理该异常,并输出异常信息,最后程序中断,退出程序。

还有我们的java程序如果我们程序员不处理异常,默认throws所以也就解释了为啥出现异常,程序便会中断,因为默认是throws机制处理异常,然后抛给JVM处理异常,打印异常信息,直接退出程序。


try-catch异常处理

我们刚刚介绍了try-catch处理异常的机制,我们现在来深入学习一下try-catch异常处理的一些细节!!

image.pngX

可以看到java提供try和catch块来处理异常,try代码块中包含可能出错的代码,catch捕捉try块中出现的异常,如果捕捉到该异常,就在catch代码块中进行异常处理,打印异常等等,而try-cath-finally组合处理异常,finally代码块中不管是否捕捉到异常都将最后执行,并且一定会被执行!!也可以没有finally代码块,try-catch组合处理异常!

注意事项

我们通过下面的代码案例来学习一些try-catch异常处理的细节吧!

//案例一
public class TryCatchDetail {
public static void main(String[] args) {
//ctrl + atl + t 快捷键 try-catch-finally语句!
//1. 如果异常发生了,则异常发生后面的代码不会执行,直接进入到 catch 块
//2. 如果异常没有发生,则顺序执行 try 的代码块,不会进入到 catch
//3. 如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用如下代码- finally
try {
String str = "bug郭";
int a = Integer.parseInt(str);
System.out.println("数字:" + a);
} catch (NumberFormatException e) {
System.out.println("异常信息=" + e.getMessage());
} finally {
System.out.println("finally 代码块被执行...");
}
System.out.println("程序继续...");
}
}

image.png

//案例二
class Person {
    private String name = "jack";
    public String getName() {
        return name;
    }
}
public class TryCatchDetail02 {
    public static void main(String[] args) {
//1.如果 try 代码块有可能有多个异常
//2.可以使用多个 catch 分别捕获不同的异常,相应处理
//3.要求子类异常写在前面,父类异常写在后面
        try {
            Person person = new Person();
            //person = null;
            System.out.println(person.getName());//NullPointerException
            int n1 = 10;
            int n2 = 0;
            int res = n1 / n2;//ArithmeticException
        } catch (NullPointerException e) {
            System.out.println("空指针异常=" + e.getMessage());
        } catch (ArithmeticException e) {
            System.out.println("算术异常=" + e.getMessage());
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
        }
    }
}

image.png

Plain Text

自动换行

xxxxxxxxxx

 

1

//案例三

2

public class TryCatchDetail03 {

3

public static void main(String[] args) {

4

/*

5

可以进行 try-finally 配合使用, 这种用法相当于没有捕获异常,

6

因此程序会直接崩掉/退出。应用场景,就是执行一段代码,不管是否发生异常,

7

都必须执行某个业务逻辑

8

*/

9

try{

10

int n1 = 10;

11

int n2 = 0;

12

System.out.println(n1 / n2);

13

}finally {

14

System.out.println("执行了 finally..");

15

}

16

System.out.println("程序继续执行..");

17

}

18

}

image.png

总结:


try-catch-finally异常处理可以有多种组合,try-catch(捕捉异常,不善后,程序继续运行,),try-finally(不捕捉异常,finally代码块一定会执行)


可以有多个catch语句,并且需要遵循异常子类在前原则,否者在前捕获到了异常,后面子类就会无法通过编译报错!


如果有fianlly代码块,那里面的语句一定为执行,不管是否捕捉了异常!!!


try-catch异常处理小测试

既然已经学到这里了,那我们来巩固测试一下!读代码写结果吧!


//测试一
public class Test_2 {
    public static int method(){
        try {
            String[] names = new String[3];//String[]数组
            if(names[1].equals("bug郭")){
                System.out.println(names[1]);
            }else {
                names[3] = "java";
            }
            return 1;
        }catch (ArrayIndexOutOfBoundsException e) {
            return 2;
        } catch (NullPointerException e) {
            return 3;
        } finally {
           return 4;
        }
    }
    public static void main(String[] args) {
        System.out.println(method());//执行结果?
    }
}
//测试一题解
public class Test_2 {
    public static int method(){
        try {
            String[] names = new String[3];//String[]数组
            if(names[1].equals("bug郭")){//null空指针异常names数组里的元素为null 
                System.out.println(names[1]);
            }else {
                names[3] = "java";
            }
            return 1;
        }catch (ArrayIndexOutOfBoundsException e) {
            return 2;
        } catch (NullPointerException e) {
            return 3;//捕捉到异常 先将3保存
        } finally {
           return 4; //一定要执行 所以最后return 4!!!
        }
    }
    public static void main(String[] args) {
        System.out.println(method());//执行结果:4
    }
}

image.png


//测试二
public class Test_3 {
    public static int method(){
        int i =1;
        try {
            i++;
            String[] names = new String[3];//String[]数组
            if(names[1].equals("bug郭")){//空指针
                System.out.println(names[1]);
            }else {
                names[3] = "java";
            }
            return 1;
        }catch (ArrayIndexOutOfBoundsException e) {
            return 2;
        } catch (NullPointerException e) {
            return ++i;
        } finally {
            return ++i;
        }
    }
    public static void main(String[] args) {
        System.out.println(method());//执行结果?
    }
}
//测试二题解
public class Test_3 {
    public static int method(){
        int i =1;
        try {
            i++; //i=2!
            String[] names = new String[3];//String[]数组
            if(names[1].equals("bug郭")){//空指针异常直接执行catch语句!
                System.out.println(names[1]);
            }else {
                names[3] = "java";
            }
            return 1;
        }catch (ArrayIndexOutOfBoundsException e) {
            return 2;
        } catch (NullPointerException e) {
            return ++i; //i = 3 并且保存了将要返回值为3 
        } finally {
            return ++i; //i = 4 一定要执行,将 i = 4返回!
        }
    }
    public static void main(String[] args) {
        System.out.println(method());//执行结果:4!!!
    }
}

image.png

//测试三
public class Test_4 {
    public static int method(){
        int i =1;
        try {
            i++;
            String[] names = new String[3];
            if(names[1].equals("bug郭")){
                System.out.println(names[1]);
            }else {
                names[3] = "java";
            }
            return 1;
        }catch (ArrayIndexOutOfBoundsException e) {
            return 2;
        } catch (NullPointerException e) {
            return ++i;
        } finally {
            ++i;
            System.out.println("i="+i);
        }
    }
    public static void main(String[] args) {
        System.out.println(method());//执行结果?
    }
}X
//测试三题解
public class Test_4 {
    public static int method(){
        int i =1;
        try {
            i++;//i=2
            String[] names = new String[3];
            if(names[1].equals("bug郭")){//空指针异常
                System.out.println(names[1]);
            }else {
                names[3] = "java";
            }
            return 1;
        }catch (ArrayIndexOutOfBoundsException e) {
            return 2;
        } catch (NullPointerException e) {
            return ++i; //i = 3 并且用临时变量保存了该返回值3!
        } finally {
            ++i; // i = 4
            System.out.println("i="+i); //打印 i= 4
        }
    } //最终函数返回:3
    public static void main(String[] args) {
        System.out.println(method());//执行结果:i= 4  3
    }
}

image.png


throws异常处理

基本介绍

throws异常处理是java处理异常的另一种方式,也是JVM的默认处理机制!

刚刚我们也已经介绍过了!

简单说就是:如果一个方法中的某处代码出现了异常,那么该方法就要进行异常异常处理!try-catch或者throws(如果不对异常进行处理那么默认也是throws)而throws处理机制就是将异常(向上一级抛)抛给方法的调用者,如果调用者都不进行异常处理,那么最终会有JVM处理,程序中断!


//throws异常处理细节!
public class ThrowsDetail {
    public static void main(String[] args) {
        f2();
    }
    public static void f2() /*throws ArithmeticException*/ {
//1.对于编译异常,程序中必须处理,比如 try-catch 或者 throws
//2.对于运行时异常,程序中如果没有处理,默认就是 throws 的方式处理
        int n1 = 10;
        int n2 = 0;
        double res = n1 / n2;
    }
    public static void f1() throws FileNotFoundException {
//这里大家思考问题 调用 f3() 报错
//解答
//1. 因为 f3() 方法抛出的是一个编译异常
//2. 即这时,就要 f1() 必须处理这个编译异常
//3. 在 f1() 中,要么 try-catch-finally ,或者继续 throws 这个编译异常
        f3(); // 抛出异常
    }
    public static void f3() throws FileNotFoundException {
        FileInputStream fis = new FileInputStream("d://aa.txt");
    }
    public static void f4() {
//解答:
//1. 在 f4()中调用方法 f5() 是 OK
//2. 原因是 f5() 抛出的是运行异常
//3. 而 java 中,并不要求程序员显示处理,因为有默认处理机制
        f5();
    }
    public static void f5() throws ArithmeticException {
    }
}
class Father { //父类
    public void method() throws RuntimeException {
    }
}
class Son extends Father {//子类
    //3. 子类重写父类的方法时,对抛出异常的规定:子类重写的方法,
// 所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常类型的子类型
//4. 在 throws 过程中,如果有方法 try-catch , 就相当于处理异常,就可以不必 throws
    @Override
    public void method() throws ArithmeticException {
    }
}

自定义异常

基本概念

当程序中出现某些“错误”,但该错误信息并没有在Throwable子类中描述处理,这个时候我们可以自己设计异常类,用于描述该错误信息。

自定义异常步骤

1.定义类:自定义异常类名(设计者自己编写)继承Exception或RuntimeException

2.如果继承Exception,属于编译异常

3.如果继承RuntimeException,属于运行异常(一般来说,继承RuntimeException)

实例

客户需求:当我们接收Person对象年龄时,要求范围在18-120之间,否者抛出一个自定义异常,并给出提示!


//解决方案
public class CustomException {
public static void main(String[] args) /*throws AgeException*/ {
int age = 180;
//要求范围在 18 – 120 之间,否则抛出一个自定义异常
if(!(age >= 18 && age <= 120)) {
//这里我们可以通过构造器,设置信息
throw new AgeException("年龄需要在 18~120 之间");
}
System.out.println("你的年龄范围正确.");
}
}
//自定义一个异常
//解读
//1. 一般情况下,我们自定义异常是继承 RuntimeException
//2. 即把自定义异常做成 运行时异常,好处时,我们可以使用默认的处理机制
//3. 即比较方便
class AgeException extends RuntimeException {
public AgeException(String message) {//构造器
super(message);
}
}

throw和throws的区别

image.png

java异常章节学习到这里!如果对大家有所帮助,还望多多支持!如有错误多多指正!内容来自bug郭在B站学习韩顺平的java课程自己整理的笔记!

互关互访互相支持,一起进步!、~

目录
相关文章
|
12天前
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
|
12天前
|
Java
在 Java 中,如何自定义`NumberFormatException`异常
在Java中,自定义`NumberFormatException`异常可以通过继承`IllegalArgumentException`类并重写其构造方法来实现。自定义异常类可以添加额外的错误信息或行为,以便更精确地处理特定的数字格式转换错误。
|
15天前
|
Java 编译器
探索Java中的异常处理机制
【10月更文挑战第35天】在Java的世界中,异常是程序运行过程中不可避免的一部分。本文将通过通俗易懂的语言和生动的比喻,带你了解Java中的异常处理机制,包括异常的类型、如何捕获和处理异常,以及如何在代码中有效地利用异常处理来提升程序的健壮性。让我们一起走进Java的异常世界,学习如何优雅地面对和解决问题吧!
|
4天前
|
安全 Java 程序员
Java中的异常处理:从新手到专家
在Java编程的世界里,异常处理是每个开发者必须面对的挑战。本文将带你从基础的异常概念出发,逐步深入到高级处理技巧,让你在遇到代码中的“意外”时,能够从容应对,甚至化险为夷。
|
9天前
|
Java 数据库连接 开发者
Java中的异常处理:从基础到高级
【10月更文挑战第42天】在Java的世界中,异常处理是维护程序稳定性和健壮性的关键。本文将带你深入了解Java的异常处理机制,从基本的try-catch语句出发,逐步探索更复杂的异常处理策略。我们将通过实际代码示例来演示如何捕获和处理异常,以及如何自定义异常类型来满足特定需求。无论你是Java新手还是有经验的开发者,这篇文章都将帮助你更好地理解和应用Java的异常处理。
|
13天前
|
IDE 前端开发 Java
怎样避免 Java 中的 NoSuchFieldError 异常
在Java中避免NoSuchFieldError异常的关键在于确保类路径下没有不同版本的类文件冲突,避免反射时使用不存在的字段,以及确保所有依赖库版本兼容。编译和运行时使用的类版本应保持一致。
|
14天前
|
Java 编译器
如何避免在 Java 中出现 NoSuchElementException 异常
在Java中,`NoSuchElementException`通常发生在使用迭代器、枚举或流等遍历集合时,尝试访问不存在的元素。为了避免该异常,可以在访问前检查是否有下一个元素(如使用`hasNext()`方法),或者使用`Optional`类处理可能为空的情况。正确管理集合边界和条件判断是关键。
|
15天前
|
Java 开发者
Java中的异常处理:从基础到高级
【10月更文挑战第35天】在Java的世界里,异常处理是维护程序健壮性的关键。本文将深入浅出地探讨Java的异常处理机制,从基本的try-catch语句到自定义异常类的实现,带领读者理解并掌握如何在Java中优雅地处理错误和异常。我们将通过实际代码示例,展示如何捕获、处理以及预防潜在的运行时错误,确保程序即使在面临意外情况时也能保持稳定运行。
33 7
|
15天前
|
Java 数据库连接 开发者
Java中的异常处理机制及其最佳实践####
在本文中,我们将探讨Java编程语言中的异常处理机制。通过深入分析try-catch语句、throws关键字以及自定义异常的创建与使用,我们旨在揭示如何有效地管理和响应程序运行中的错误和异常情况。此外,本文还将讨论一些最佳实践,以帮助开发者编写更加健壮和易于维护的代码。 ####
|
18天前
|
Java
Java 异常处理下篇:11 个异常处理最佳实践
本文深入探讨了 Java 异常处理的最佳实践,包括早抛出晚捕获、只捕获可处理的异常、不要忽略捕获的异常、抛出具体检查性异常、正确包装自定义异常、记录或抛出异常但不同时执行、避免在 `finally` 块中抛出异常、避免使用异常进行流程控制、使用模板方法处理重复的 `try-catch`、尽量只抛出与方法相关的异常以及异常处理后清理资源。通过遵循这些实践,可以提高代码的健壮性和可维护性。
下一篇
无影云桌面