【JAVA学习笔记】47 - 异常,try-catch处理,throw处理

项目代码

https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter12/scr/com/yinhai/exception_

〇、异常处理的引入

程序出现一个小问题如int num1 = 10;int num2 = 0;num1 / num2 => 10 / 0

会抛出错误,但这样不算致命的小问题就导致程序崩溃不应该,健壮性太差

所以引出异常处理-异常捕获try-catch

对于可能出现问题的代码使用ctrl + alt + t选中

java 复制代码
/**
 * @author 银海
 * @version 1.0
 */
public class Exception01 {
    public static void main(String[] args)  {
        int num1 = 10;
        int num2 = 0;//Scanner();
        //1. num1 / num2 => 10 / 0
        //2. 当执行到 num1 / num2 因为 num2 = 0, 程序就会出现(抛出)异常 ArithmeticException
        //3. 当抛出异常后,程序就退出,崩溃了 , 下面的代码就不在执行
        //4. 这样的程序不好,不应该出现了一个不算致命的问题,就导致整个系统崩溃,健重性太次
        //5. java 设计者,提供了一个叫 异常处理机制来解决该问题
        // int res = num1 / num2;
        //如果程序员,认为一段代码可能出现异常/问题,可以使用try-catch异常处理机制来解决
        //从而保证程序的健壮性
        //将该代码块->选中->快捷键 ctrl + alt + t -> 选中 try-catch
        //6. 如果进行异常处理,那么即使出现了异常,程序可以继续执行
        try {
            int res = num1 / num2;
        } catch (Exception e) {
            //e.printStackTrace();
            System.out.println("出现异常的原因=" + e.getMessage());//输出异常信息
        }

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

    }
}

一、异常的基本介绍

基本概念

Java语言中,将程序执行中发生的不正常情况称为"异常"。(开发过程中的语法错误和逻辑错误不是异常)

执行过程中所发生的异常事件

可分为两类

1.Error(错误): Java虚拟机无法解决的严重问题。如: JVM系统内部错误、资源耗尽等严重情况。比如: StackOverflowError[栈溢出]和OOM(out ofmemory内存不足), Error 是严重错误,程序会崩溃。

2.Exception(异常):其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等,

Exception异常又分为两大类

运行时异常(程序运行时发生的)和编译时异常(编程时,编译器检查出的)。〇所演示的是运行时异常

1)运行时异常,编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常

2)对于运行时异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响

3)编译时异常,是编译器要求必须处置的异常。

二、异常体系图

如何在IDEA内查看上面的类图体系图呢

1.从Exception类跳转到Throuwable根类,使用Ctrl+B

  1. 右键Throwable类的代码编辑的空白处,点击Diagrams

3.在打开的Diagrams, 右键Throable,选择show Implementations,快捷键Ctrl + Alt +B

show Parent 展示所继承的父类

4.在弹出的接口框中使用键盘输入需要查看的类

5.完成 蓝色线表示继承,绿色线表示调用接口

三、常见的运行时异常

1.NullPointerException空指针

当应用程序试图在需要对象的地方使用nul时,抛出该异常。

2.ArithmeticException运算异常

当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例

3.ArrayIndexOutOfBoundsExceptiont非法索引异常

用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则,该索引为非法索引

4. ClassCastException类型转换异常

当试图将对象强制转换为不是实例的子类时,抛出该异常。例如,以下代码将生成一个

5.NumberFormatException数字格式不正确异常

当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常=>使用异常我们可以确保输入是满足条件数字,

Integer.parseInt();解析字符串并返回相应的整数值

四、编译异常

编译异常是指在编译期间,就必须处理的异常,否则代码不能通过编译。了解即可

常见的编译异常

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

lOException //操作文件时,发生的异常

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

ClassNotFoundException //加载类,而该类不存在时,异常

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

llegalArguementException //参数异常

五、异常课堂练习

六、异常处理

基本介绍

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

处理的方式

处理方式只能二选一,要么1要么2

1.try-catch-finally

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

java 复制代码
try {
    //代码/可能有异常
}catch(Exception e) {
    //捕获到异常
    //1.当异常发生时
    //2.系统将异常封装成Exception对象e,传递给catch
    //3得到异常对象后,程序员,自己处理
    //4.注意,如果没有发生异常catch代码块不执行
}finally{
    //1.不管try代码块是否有异常发生,始终要执行finally
    //2.所以,通常将释放资源的代码,放在finally
}
2.throws

将发生的异常抛出,交给调用方法来处理,最顶级的处理者就是JVM。如果扔给JVM,会直接输出异常信息然后退出程序,如果没有显式的处理方法则默认throw,一直扔到最高的JVM

七、try-catch异常处理

1.Java提供try和catch块来处理异常。

try块用于包含 可能出错的代码。catch块用于处理try块中发生的异常。可以根据需要在程序中有多个数量的try..catch块。

2.基本语法

try {

//可疑代码

//将异常生成对应的异常对象,传递给catch块

}catch(异常){

//对异常的处理

}finnaly{

//无论有没有异常都会执行

}

3.try-catch注意事项和细节

1)如果异常发生了,则异常发生try块内后面的代码不会执行,直接进入到catch块,注意catch完之后程序依然会执行
java 复制代码
public class TryCatchDetail {
    public static void main(String[] args) {
        //ctrl + alt + T
        try {
            String str = "yinhai";
            int a = Integer.parseInt(str);
            System.out.println("数字" + a);
        } catch (NumberFormatException e) {
            System.out.println(e.getMessage());
        }
        System.out.println("程序继续");
    }
}
2)如果异常没有发生,则顺序执行try的代码块,不会进入到catch.
java 复制代码
String str = "123";
3)如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用如下代码finally {}
java 复制代码
finally {
            System.out.println("finally 代码块被执行");
        }
4)可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception 在后,NullPointerException 在前),如果发生异常,只会匹配一个catch
java 复制代码
public class TryCatchDetail02 {
    public static void main(String[] args) {
        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
        } 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 {
            
        }
    }
}
5)可以进行try-finally配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉,finally进行善后工作,
java 复制代码
public class TryCatchDetail03 {
    public static void main(String[] args) {
        try {
            int n1 = 10;
            int n2 = 0;
            System.out.println(n1 / n2);
        } finally {
            System.out.println("执行了finally");
        }
        System.out.println("程序继续执行");
    }
}

八、try - catch课堂练习

1.

2.

3.

注意,这里的catch内的return会在finally执行完毕后返回,而且在执行到return ++i的时候会用一个临时变量temp保存当前的i值,返回的是temp值

所以method确实是返回3

小结

try-catch-finally执行顺序小结

1)如果没有出现异常,则执行try块中所有语句,不执行catch块中语句,如果有finally,最后还需要执行finally里面的语句

2)如果出现异常,则try块中异常发生后,try块剩下的语句不再执行。将执行catch块中的语句,如果有finally, 最后还需要执行finally里面的语句

课后练习

如果用户输入的不是一个整数,就提示他反复输入,直到输入一一个整数为止

使用try catch来控制,再用Integer来获取String转成Int 试试

java 复制代码
/**
 * @author 银海
 * @version 1.0
 */
public class TryCatchExcerise {
    public static void main(String[] args) {
        String name = "";
        Scanner scanner = new Scanner(System.in);
        while(true){
            try {
                System.out.println("请输入一个整数");
                name = scanner.next();
                System.out.println("输入的信息为" + name);
                int num = Integer.parseInt(name);//因为执行到这里如果为错误会报错 下面的语句不会执行 跳转到catch语句块
                System.out.println("成功获取整数=" + num);
                break;
            } catch (NumberFormatException e) {
                System.out.println("错误信息为" + e.getMessage() + "请重试");
                continue;//跳到while继续循环
            }
        }
    }
}

九、throws异常处理

1.基本介绍

1)如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。

2)在方法声明中用throws语句可以声明抛出异常的列表(抛出多个异常),throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。

java 复制代码
public class Throw01 {
    public static void main(String[] args) {


    }
    //public void f1() throws Exception{
    public void f1() throws FileNotFoundException{
        // public void f1() throws ArithmeticException,NullPointerException{
        //创建一个文件流对象
        //这里的异常是FileNotFoundException
        //这里可以使用两种异常处理方法
        //1.try catch
        //2.throws 抛出异常,让调用这个f1方法的调用者(方法)处理
        //使用throws可以抛给调用者,也可以抛给父类
        //throws 关键字后也可以是异常列表,即可以抛出多个异常
        FileInputStream fi = new FileInputStream("e://aa.txt");
    }
}

2.throws的细节处理和注意事项

1)对于编译异常,程序中必须处理,比如try-catch或者throws
2)对于运行时异常,程序中如果没有处理,默认就是throws的方式处理
3)子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致, 要么为父类抛出的异常的类型的子类型
java 复制代码
class Father{//父类
    public void method() throws RuntimeException{

    }
}
class Son extends Father{
    //子类重写父类的方法时,对抛出异常的规定:
    // 子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类方法抛出的异常的类型的子类型
    @Override
    public void method() throws NullPointerException{//Null 是Runtime 的子类所以没有报错
    // public void method() throws Exception{//Null 是Runtime 的子类所以没有报错

    }
}

如果异常类型不是子类则会报错

4)在throws过程中,如果有方法try-catch,就相当于处理异常,就可以不必throws(二选一)
5)对于调用已经throws的方法,什么都不做会报错异常,需要将调用者(方法)再显式的throws一次

注意只要throws就需要再显式调用,不然会报错

6)对于抛出的是RunTime时的异常,编译器并不会报错,不需要再显式的定义throws

在java中有默认处理,及JVM默认报错退出程序

java 复制代码
public class ThrowsDetail {
    public static void main(String[] args) throws FileNotFoundException {
        f1();
        f4();
    }
    public static void f1()throws FileNotFoundException{
        f3();//抛出异常 因为这个f3()方法抛出的是编译异常
        // 即这时要求f1也必须显式的处理这个编译异常可以throw抛给父类
    }
    public static void f3()throws FileNotFoundException{
        // FileInputStream fi = new FileInputStream("e://aa.txt");
    }
    public static void f4(){
        f5();
    }
    public static void f5() throws RuntimeException{
        //对于抛出的是RunTime时的异常,f4调用f5编译器并不会报错,不需要再显式的定义throws

    }
}
class Father{//父类
    public void method() throws RuntimeException{

    }
}
class Son extends Father{
    //子类重写父类的方法时,对抛出异常的规定:
    // 子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类方法抛出的异常的类型的子类型
    @Override
    public void method() throws NullPointerException{//Null 是Runtime 的子类所以没有报错
    // public void method() throws Exception{//Null 是Runtime 的子类所以没有报错

    }
}

十、自定义异常

基本概念

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

自定义异常步骤

自定义异常的步骤

1)定义类:自定义异常类名(程序员自己写)继承Exception或RuntimeException

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

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

java 复制代码
public class CustomException {
    public static void main(String[] args) {
        int age = 0;
        if (!(age >= 18&& age <= 120)) {
            throw new AgeException("年龄需要在18~120之间");
        }
    }
}
//一般继承RuntimeException,把自定义异常做成自定义异常,我们可以使用默认的处理机制
class AgeException extends RuntimeException{
    public AgeException(String message){
        super(message);
    }
}

十一、throw

1.throw和throws的区别

throw表示扔出具体的异常对象,而throws扔出的是异常类型

2.throw的课堂练习

十二、异常的课后练习

1.

a)编写应用程序EcmDefjava,接收命令行的两个参数(整数),计算两数相除。

b)计算两个数相除,要求使用方法cal(int n1, int n2)

c)对数据格式不正确、缺少命令行参数、除0进行异常处理。

java 复制代码
 public class Homework01 {
    public static void main(String[] args) {

        //验证输入的个数是否正确
        try {
            if(args.length != 2){
                throw new ArrayIndexOutOfBoundsException("数组长度异常");
            }
            int n1 = Integer.parseInt(args[0]);
            int n2 = Integer.parseInt(args[1]);
            double res = cal(n1,n2);//该方法可能抛出算术异常
            System.out.println("算术结果是" + res);
        } catch (ArrayIndexOutOfBoundsException e){
            System.out.println("参数个数不对");
        }
        catch (NumberFormatException e) {
            System.out.println("参数格式不对,请输入整数");
        }catch (ArithmeticException e){
            System.out.println("出现除数为0");
        }


    }
    public static double cal(int n1,int n2){
        return n1/n2;
    }
}

用IDEA多了 命令控制台生疏了,编了几次都是无法加载类名,因为有全限定名在所以定位不到该class文件,更改一下即可参考 Java命令行运行错误: 找不到或无法加载主类_明月几时有666的博客-CSDN博客

2.

3.

4.

相关推荐
取酒鱼食--【余九】几秒前
机器人学基础(一)【坐标系和位姿变换】
笔记·算法·机器人·开源·机器人运动学·机器人学基础
西西学代码2 分钟前
Flutter---showCupertinoDialog
java·前端·flutter
多多*5 分钟前
上传文件相关业务,采用策略模式+模版方法模式进行动态解耦
java·开发语言
晨非辰6 分钟前
【面试高频数据结构(四)】--《从单链到双链的进阶,读懂“双向奔赴”的算法之美与效率权衡》
java·数据结构·c++·人工智能·算法·机器学习·面试
im_AMBER6 分钟前
数据结构 03 栈和队列
数据结构·学习·算法
沐雨橙风ιε11 分钟前
Spring Boot整合Apache Shiro权限认证框架(实战篇)
java·spring boot·后端·apache shiro
左师佑图17 分钟前
Apache POI SXSSFWorkbook 报错“没有那个文件或目录”问题排查与解决方案
java·apache·excel
凸头24 分钟前
以AtomicInteger为例的Atomic 类的底层CAS细节理解
java·jvm·算法
艾派森28 分钟前
基于 Rokid CXR-M SDK 构建 AR 远程专家协作系统:从零实现眼镜端自定义 UI 与实时交互
java
我先去打把游戏先35 分钟前
VSCode通过SSH连接到Ubuntu虚拟机失败“找不到ssh安装”问题解决
笔记·vscode·单片机·嵌入式硬件·学习·ubuntu·ssh