首页 > 编程语言 >Java-Day-15( 异常 )

Java-Day-15( 异常 )

时间:2023-04-24 11:33:24浏览次数:40  
标签:Java int System public finally catch 15 异常 Day

Java-Day-15

异常

引出异常

( Exception )

  • 如:零成分母时,会抛出 ArithmeticException 异常,然后程序就会崩溃退出,下面的代码也就不执行了

    • 但这种不出现致命错误就使得系统崩溃就不合理了
    • 所以设计者提供了异常处理机制来解决此问题
  • 解决方式 — 异常捕获

    • 如果程序员认为一段代码可能出现异常 / 问题,可以使用 try-catch 异常处理机制来解决,从而保证程序的健壮性

    • 选中代码后快捷键 ctrl + alt + t 选中 try - catch

    • 处理后即使出现了异常,程序仍可以继续执行

      int n1 = 1;
      int n2 = 0;
      try {
          int res = n1 / n2;
      } catch (Exception e) {
          System.out.println("出现异常的原因是:" + e.getMessage());
      }
      
  • 异常介绍

    • java语言中,将程序执行中发生的不正常情况称为 ”异常“。
      • 开发过程中语法的错误和逻辑错误不是异常
  • 执行过程中所发生的异常事件可分为两类

    • Error ( 错误 ):Java 虚拟机无法解决的严重问题,如:JVM 系统内部错误、资源耗尽等严重情况。
      • StackOverflowError [ 栈溢出 ] 和 OOM ( out of memory ),Error 是严重错误,程序会崩溃
    • Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理,如:空指针访问,试图读取不存在的文件,网络连接中断等待
      • 往下还分两大类:运行时异常 [ 程序运行时,发生的异常 ] 和编译时异常 [ 编程时,编译器检查出的异常 ]
  • 异常体系图

    • idea 里,在 Throwable 源码里右键打开类图

      image-20230423185850874

    • 查找分支

      image-20230423185924488

    • 完成异常体系图

      image-20230424105601284

    • 虚线:实现类箭头指向的接口

    • 实线:继承了箭头指向的类

  • Java 源程序 —— ( 编译异常 ) ——> 字节码文件 —— ( 运行异常 ) ——> 内存中加载、运行类

  • 异常分为两大类,运行时异常和编译时异常

    • 运行时异常,是编译器不要求强制处置的异常,一般是指编程时的逻辑错误,是程序员应该避免其出现的异常
      • 对于运行时异常,可以不做处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响
    • 而编译时异常是编译器要求必须处置的异常
      • 一般像 idea 都会红色波浪线标出来

常见运行异常

  • NullPointerException 空指针异常:当应用程序试图在需要对象的地方却使用了 null 时,抛出该异常

    String name = null;
    System.out.println(name.length());
    
  • ArithmeticException 数学运算异常:当出现异常的运算条件时,抛出此异常

    int n1 = 1;
    int n2 = 0;
    int res = n1 / n2;
    
  • ArrayIndexOutOfBoundsException 数组下标越界异常:用非法索引访问数组时抛出的异常

    • 缺少命令行参数
    int[] arr = {1, 2};
    // for (int i = 0; i < arr.length; i++) { 正确
    for (int i = 0; i <= arr.length; i++) {
        //  数组从0开始,只有0、1,到不了2
    }
    
  • ClassCastException 类型转换异常:当试图将对象强制转换为不是实例的子类时,抛出该异常

    class B extends A {}
    class C extends A {}
    
    // main
    A b = new B();
    C c = (C)b;
    
  • NumberFormatException 数字格式不正确异常:当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常 ( 使用异常来确保输入是满足条件的数字 )

    String name = "啦啦啦";
    int num = Integer.parseInt(name);
    

编译异常

  • 编译期间就必须处理的异常,否则代码不能通过编译
  • 常见的编译异常
    • SQLException // 操作数据库时,查询表可能发生异常
    • IOException // 操作文件时发生的异常
    • FileNoFoundException // 操作一个不存在的文件时发生的异常
    • ClassNotFoundException // 加载不存在的类时
    • EOFException // 操作文件到文件末尾,发生异常
    • IllegalArguementException // 参数异常

异常处理

  • 以下两种处理方式二选一

  • try-catch-finally

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

      try {
      //    代码 / 可能有异常
      } catch(Exception e) {
      //    捕获到异常
      //    当异常发生时,系统将异常封装成 Exception 对象 e,传递给 catch
      //    得到异常对象后,程序员自行处理
      //    如果没有发生异常,此处代码块不执行
      } finally {
      //    不管 try 代码块是否有异常发生,始终要执行 finally,也可以选择不写 finally
      //    所以通常将释放资源的代码放在此处
      }
      
    • 注意细节

      • 如果异常发生,就不再继续执行后面代码,直接进入 catch 块
      • 如果异常没有发生,则顺序执行 try 代码块,不进 catch
      • 如果希望不管是否发生异常都执行某段代码,用 finally
    • 如果 try 代码有多个异常,就使用多个 catch 分别捕获不同的异常,相应处理

      • 但要求子类异常写在前面,父类异常写在后面

        catch { ... } catch

    • 可以直接 try-finally,但这样相当于没有捕获异常,因此程序会直接崩掉 / 退出

    try{
        int n1 = 10;
        int n2 = 0;
        System.out.println(n1 / n2)
    }finally {
        System.out.println("执行了finally");
    }
    System.out.println("程序继续执行");
    
    // 若是n2不为零,就会输出计算结果和两条System输出语句
    // 如上述代码的话,就只输出:“执行了finally” 
    // 后面一切代码包括后面的System都不会执行
    
    • 应用:不管是否发生异常,都必须执行某个业务逻辑
  • throws ( 默认方式 )

    • 如果一个方法 ( 中的语句执行时 ) 可能生成某种异常,但并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而交给该方法的调用者来处理,最顶级的处理者就是 JVM

      • JVM 处理:输出异常信息,退出程序.
      • 就是平常默认的出错方式
    • 在方法的声明中用 throws 语句可以声明抛出异常的列表,throws 后面的异常类型可以是方法中产生的异常类型,也可以是异常的父类 ( Exception )

      public class test {
          public static void main(String[] args){
          }
      //      使用第二种方法:throws,抛出异常,让调用f1方法的调用者(方法)处理
      //    public void f1() throws FileNotFoundException {
      //      throws后面也可以是异常列表,即可以抛出多个异常
      //    public void f1() throws FileNotFoundException,NullPointerException {
      //      或者直接用异常的父类,全包括了
          public void f1() throws Exception {
              FileInputStream fis = new FileInputStream("d://aa.txt");
          }
      }
      
    • 注意细节

      • 编译异常必须要处理 ( 会标红 )

      • 对于运行时异常,程序中如果没有处理,默认就是 throws 的方式处理 ( 最终就是抛给了 JVM )

      • 子类重写父类方法时,对抛出异常的规定:子类重写的方法,所抛出的异常要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型

        // 从先前画的异常体系图可以看出NullPointerException是RuntimeException的子类
        class Father {
            public void method() throws RuntimeException { }
        }
        
        class Son extends Father {
            @Override
            public void method() throws NullPointerException { }
        }
        
      • 编译异常时,方法显示地声明抛出异常,表明该方法将不对这些异常进行处理,而交给该方法的调用者来处理,则调用者 ( 即下述的 f2() ) 要不 try-catch,要不继续 throws

         public void f1() throws FileNotFoundException {
             FileInputStream fis = new FileInputStream("d://aa.txt");
            }
        
        // 若是这个时候有一个方法调用了这个抛出异常的方法f1
        // 只这样写会报错
        // public static f2() {
        // F1:
        public static f2() throws FileNotFoundException {
            f1();
        }
        
        // F2:
        public static f2() {
            try {
                f1();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        
      • 运行异常时,是存在默认处理的,而 java 中并不要求程序员显式处理,因为有默认处理机制

        public static f3() throws AirthmeticException {
        }
        public static f4() {
        // 不会报错
            f3();
        }
        
  • 练习

    • 看输出什么

      public class test {
          public static void main(String[] args){
              System.out.println(Exception.method());
          }
      }
      
      class Exception {
          public static int method(){
              int i = 1;
              try {
                  i++;   // i=2
                  String[] names = new String[3];
                  if (names[1].equals("tom")) { // 空指针错误直接跳到Null...
                      System.out.println(names[1]);
                  } else {
                      names[3] = "zhuyazhu";
                  }
                  return 1;
              } catch (ArrayIndexOutOfBoundsException e) {
                  return 2;
              } catch (NullPointerException e){
                  return ++i;  // i=3,但还有finally,return不会马上执行,在底层会临时变量temp=3保存
              } finally {
                  ++i;   // i=4
                  System.out.println("i=" + i);  // 输出 i=4
              }
          }
      }
      
      • 输出为
        i=4
        3

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

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

      • 如果没有 catch 捕获,就 finally 后强行退出程序 ( 如果有 finally 的话 ),捕获了的话就继续执行

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

      public class test {
          public static void main(String[] args){
              Scanner scanner = new Scanner(System.in);
              int num = 0;
              while(true){
                  try {
                      System.out.println("请输入一个整数:");
                      num = Integer.parseInt(scanner.next());
                      break;
                  } catch (NumberFormatException e) {
                      System.out.println("你输入的不是个整数");
                  }
              }
              System.out.println("你输入的值是=" + num);
          }
      }
      

自定义异常

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

    • 好处就是可以使用默认的处理机制
  • 自定义异常的步骤

    • 定义类:自定义异常类名 ( 程序员自己写 ) 继承Exception 或 RuntimeException
    • 如果继承 Exception,属于编译异常
      • 若是用编译异常,就要在调用其的方法里 ( 如:main ) 也要 throws 自定义的异常
    • 如果继承 RuntimeException,属于运行异常 ( 一般来说,继承 RuntimeException )
  • 应用

    • 当接收 Person 对象年龄时,要求范围在 18 ~ 120 之间,否则抛出一个自定义异常 ( 要求继承 RuntimeException ),并给出提示信息

      public class test {
          public static void main(String[] args) {
              int age = 80;
              if (!(age >= 18 && age <= 120)) {
                  throw new AgeException("年龄错误,应该在18~120之间");
              }
              System.out.println("输入年龄范围正确");
          }
      }
      
      //自定义异常
      class AgeException extends RuntimeException {
          public AgeException(String message) {
      //        追寻父类是一直到Throwable类,其方法即为将message信息显示于控制台提示
              super(message);
          }
      }
      
  • throw 和 throws 区别

    意义 位置 后面所跟
    throws 异常处理的一种方式 方法声明处 异常类型
    throw 手动生成异常对象的关键字 方法体中 异常对象
    • 如:在上述自定义异常时有一句 throw new AgeException("年龄错误,应该在18~120之间");
  • 练习

    • 查看输出

      public class test {
          public static void main(String[] args) {
              try {
                  ReturnExceptionDemo.methodA();
      //            从methodA中拿到throw出的异常被下面的catch捕获
              } catch (Exception e) {
      //            message:”制造异常“,在这里才被输出
                  System.out.println(e.getMessage());  								// 3
              }
              ReturnExceptionDemo.methodB();
          }
      }
      
      //自定义异常
      class ReturnExceptionDemo {
          static void methodA() {
              try {
                  System.out.println("进入方法A");  							   	 	 // 1
                  throw new RuntimeException("制造异常");  							 // 3
              } finally {
                  System.out.println("用A方法的finally");  							 // 2
              }
          }
          static void methodB() {
              try {
                  System.out.println("进入方法B"); 									  // 4
                  return;
              } finally {
                  System.out.println("用B方法的finally"); 							  // 5
              }
          }
      
      
      • 输出

        进入方法A
        用A方法的finally
        制造异常
        进入方法B
        用B方法的finally

    • 编写应用程序,接收命令行的两个参数,计算两数相除,要求使用 cal (int n1, int n2),对数据格式不正确、缺少命令行参数、除零进行异常处理

      public class test1 {
          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(e.getMessage());
              } catch (NumberFormatException e) {
                  System.out.println("参数格式不正确,需要输入整数");
              } catch (ArithmeticException e) {
                  System.out.println("出现了除以零的异常");
              }
          }
          public static double cal(int n1, int n2) {
              return n1 / n2;
          }
      }
      

标签:Java,int,System,public,finally,catch,15,异常,Day
From: https://www.cnblogs.com/zhu-ya-zhu/p/17348921.html

相关文章

  • JavaScript 基础问答
      JavaScript数据类型有哪几种?  一共有五种:number、string、object、boolean、undefined.其中最后一个是定义变量后没有赋值介绍隐式类型转换字符串+数字=字符串;字符串-数字=数字;+数字字符串=数字null经过数字转换之后会变为0undefined经过数字转换之后会变为NaN......
  • 设计模式-原型模式-Java中使用示例-节日发送邮件活动
    场景设计模式-原型模式-浅克隆和深克隆在Java中的使用示例:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/127576328上面初步记录了原型模式的使用示例,下面再记录一个银行节假日或者搞活动时发送邮件的例子。原型模式原型模式(PrototypePattern)的简单程度仅次......
  • 五分钟理解Java算法的时间复杂度
    关注我了解更多Java技术知识,带你一路“狂飙”到底!上岸大厂不是梦!前言时间复杂度主要是为了反映函数的执行时间随着输入规模增长而变化的规律,在一定程度上可以体现程序的执行效率和算法的优劣。作为程序员,掌握基本的算法时间复杂度的计算是很有必要的。时间复杂度介绍理论上,执......
  • Java-Day-14( 枚举 + 注解 + 自设头文件 )
    Java-Day-14枚举(enumeration,enum)若是创建春夏秋冬四季的信息,如果按传统方法创建,无法固定信息,可以随时调改,所以要用枚举,做到只读且不能改枚举一组常量的集合——属于一种特殊的类,里面只包含一组有限的特定的对象实现方式自定义类实现枚举构造器私有化......
  • Java 常见报错解决方案
    1.常见的java异常分类Throwable类有两个直接子类:Exception:出现的问题是可以被捕获的Check异常:派生自Exception的异常类,必须被捕获或再次声明抛出Runtime异常:派生自RuntimeException的异常类。使用throw语句可以随时抛出这种异常对象thrownewArithmeticException(…);......
  • 力扣977(Java)-有序数组的平方(简单)
    题目:给你一个按非递减顺序排序的整数数组nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。 示例1:输入:nums=[-4,-1,0,3,10]输出:[0,1,9,16,100]解释:平方后,数组变为[16,1,0,9,100]排序后,数组变为[0,1,9,16,100]示例2:输入:nums=[-7,-3,2,3,11]输出:[4,......
  • IDEA中JavaDocs路径是红色的
    转载链接:https://blog.csdn.net/Chia_Hung_Yeh/article/details/102936633ProjectSettings-->Libraries-->Sources、JavaDocs路径出现红色字体ClassesClasses中的jar,是程序在运行项目的时候使用的,因为这个是直接编译好的class文件,可以直接被虚拟机运行的。SourcesSource......
  • day54 (2023.4.23)
    1.其它查询方式-----模糊查询 实现模糊查询此时数据库中的数据查询数据库中,中间有f的,运行结果2.其它查询方式-----动态条件查询 动态条件查询实现 此时数据库中的数据 运行结果 如果不给查询条件,运行结果 3.其它查询方式-----分页查询 实现分......
  • java -- 枚举和反射
    枚举枚举概述枚举是JDK1.5新增的引用数据类型,和类,接口是一个级别的,定义枚举的关键字为enum。java.lang.Enum类,是所有枚举的父类。枚举的本质就是一个类的多个对象。枚举的定义格式:publicenmu枚举名{}枚举常量定义:枚举中的常量名字大写,多个常量之间逗号分开,最后一个常......
  • Javascript数据类型
    值类型和引用类型原始类型(alias:值类型,基础类型)primitive:stringnumberbooleannullundefinedsymbol引用类型:Object其他内置Object派送类型ArrayFunctionMapSetWeakMapWeakSetRegExpNaN:特殊的Number类型,IsNaN()判断一个值是否为NaN引用类型可以有......