Java学习【认识异常】

Java学习【认识异常】

码农世界 2024-06-04 前端 114 次浏览 0个评论

Java学习【认识异常】

  • 认识异常
    • 异常的种类
    • 异常的作用
    • 异常的处理方式
      • JVM默认的处理方式
      • 捕获异常
        • finally
        • 多个异常的处理
        • 异常中的方法
        • 抛出异常
        • 自定义异常

          认识异常

          在Java中,将程序执行过程中发生的不正常行为称为异常

          异常的种类

          Error代表的是系统级别的错误,属于严重的问题

          Exception叫做异常,代表程序可能出现的问题,通常用Exception和它的子类来封装程序所出现的问题

          运行时异常: RuntimeException及其子类,编译阶段不会出现问题,运行时出现异常(例如数组越界异常)

          编译时异常: 编译阶段就会出现异常提醒

          例如之前写的克隆接口练习,出现的异常就属于编译时异常,编译阶段必须手动进行处理,

          异常的作用

          1.用来查询bug信息

          通过异常的类型我们可以很快的发现程序的错误类型

          当运行以下代码时:

          class Student{
              private String name;
              private int age;
              public Student(String str){
                  String[] strs = str.split("-");
                  this.name = strs[0];
                  this.age = Integer.parseInt(strs[1]);
              }
              public Student(String name,int age){
                  this.name = name;
                  this.age = age;
              }
              @Override
              public String toString() {
                  return "Student{" +
                          "name='" + name + '\'' +
                          ", age=" + age +
                          '}';
              }
          }
          public class Text {
              public static void main(String[] args) {
                  Student student1 = new Student("张三,20");
                  System.out.println(student1);
              }
          }
          

          出现了数组越界的异常,通过这些可以定位到出现异常的位置

          String[] strs = str.split("-");//应该改为用","分割
          

          2.可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况

          例如当需要获取一个10~20的数字时,如果直接把不符合要求的情况打印在控制台上,这样调用处就无法得到具体的数是什么

          此时就可以通过返回异常来解决:

          异常的处理方式

          JVM默认的处理方式

          把异常的名称,异常的原因及出现的位置等信息输出在控制台

          程序停止,下面的代码不会被执行

          System.out.println("哈哈");
          System.out.println(2/0);//出现异常
          System.out.println("呵呵");
          

          异常后面的内容并没有被执行

          捕获异常

          格式:

          try{

          可能出现异常的代码;

          }catch(异常类名 变量名){

          异常的处理代码;

          }

          public static void main(String[] args) {
                  int[] arr = {1, 2, 3};
                  try {
                      System.out.println(arr[5]);/*此处出现了异常,程序在这里就会创建一个 ArrayIndexOutOfBoundsException对象
                                                   用这个对象和catch里面比较,看括号中的变量是否可以接收这个对象
                                                   如果能接收,就表示异常被捕获,接着执行catch里面的代码
                                                   之后再执行catch下面的代码*/
                  }catch (ArrayIndexOutOfBoundsException e){
                      System.out.println("数组越界异常");
                  }
                  System.out.println("程序继续执行");
              }
          

          通过捕获异常的方式处理,后续的代码是可以正常执行的

          如果try中没有遇到问题,就会把try里的代码全部执行一遍,catch里面的代码并不会被执行

          finally

          try {

          // 尝试执行的代码块

          // 如果这里发生异常,则控制流会立即跳转到相应的catch块

          } catch (ExceptionType1 e) {

          // 处理ExceptionType1类型的异常的代码块

          } finally {

          // 无论是否发生异常,都会执行的代码块

          // 通常用于执行清理操作,如关闭文件、数据库连接等

          }

          finally块里的语句,无论是否发生异常,都会执行,使用finally块的一个常见场景是确保资源(如文件句柄、网络连接或数据库连接)在使用后被正确关闭。即使发生异常,这些资源也需要在程序继续之前被释放。通过使用finally块,可以确保无论是否发生异常,这些资源都会被正确管理。

          所以,对于这个方法,最终的返回值是finally里的2

          多个异常的处理

          当同时存在多个异常的时候,就要写多个catch与之对应

          public static void main(String[] args) {
                  try {
                      String str = null;
                      str.split("");
                      System.out.println(2/0);
                  }catch (NullPointerException e){
                      System.out.println("空指针异常");
                  }catch (ArithmeticException e){
                      System.out.println("算术异常");
                  }
                  System.out.println("程序继续执行");
              }
          

          注意: 如果异常中存在继承关系,子类要写在父类之前,不然所有的异常都会被父类捕获,程序报错

          把父类写在最下面就可以了:

          如果try中遇到的问题没有被捕获,最终还是会交给虚拟机处理

          之后就会用虚拟机默认的处理方式,打印在控制台上:

          如果try中出现的问题被捕捉到了,那么出现问题的下面就不会继续被执行

          try {
                      System.out.println(arr[10]);
                      System.out.println("这里之后不会执行");
                      System.out.println(2/0);
                  } catch (ArrayIndexOutOfBoundsException e) {
                      System.out.println("数组越界异常");
                  } catch (NullPointerException e) {
                      System.out.println("空指针异常");
                  } catch (ArithmeticException e) {
                      System.out.println("算术异常");
                  } 
          

          所以后面的算术异常也不会被捕捉到

          异常中的方法

          通过快捷键ctrl + alt + t 可以快速生成 try-catch语句

          public String getMessage(): 返回throwable的详细信息字符串

          public String toString(): 返回此可抛出的简短描述

          public void printStackTrace(): 把异常的错误信息输出在控制台上

          printStackTrace方法打印的信息包含了getMessage()和toString()的信息,也最为常用

          抛出异常

          throws: 写在方法定义处,表示声明一个异常,告诉调用者,使用此方法可能会有哪些异常

          public void方法名() throws 异常类名1,异常类名2{ ···· }

          编译时异常:必须要写

          运行时异常:可以不写

          throw: 写在方法内,表示结束方法,用来手动抛出异常对象,交给调用者处理,方法中下面的代码不再执行

          public void 方法(){

          throw new 异常对象();

          }

          区别:

          throwthrow关键字用于在方法中抛出一个异常,throws关键字用于声明一个方法可能会抛出的异常,本身并不抛出异常,它只是一个声明,告诉方法的调用者这个方法在执行过程中可能会抛出哪些异常

          自定义异常

          创建自定义异常类:

          声明一个继承自Exception类或其子类的类,作为自定义异常类。

          根据需要添加构造方法和其他方法。例如,可以添加一个带有错误消息的构造方法,以便在抛出异常时提供有关异常的详细信息。

          当直接继承Exception类来创建自定义异常时,创建的是一个受检异常。受检异常是那些必须在方法签名中使用throws关键字声明,并且在调用该方法的地方使用try-catch块捕获或继续向上抛出的异常。编译器会强制要求这样做,以确保处理了所有可能的异常情况

          public class MyCustomException extends Exception {  
            
              public MyCustomException() {  
                  super();  
              }  
            
              // 带字符串消息的构造函数  
              public MyCustomException(String message) {  
                  super(message);  
              }  
              
          }
          

          继承RuntimeException类,表示的是运行时发生的异常。RuntimeException和其子类被视为未受检异常。未受检异常不需要在方法签名中声明,编译器也不会强制要求你捕获它们。

          public class PassWordException extends RuntimeException{
              public PassWordException() {
              }
              public PassWordException(String message) {
                  super(message);
              }
          }
          

          之后的使用方法和Java中的异常是一样的,这里给出一个登录系统的示例:

          public class Login {
              private String username;
              private String password;
              public Login() {
              }
              public Login(String username, String password) {
                  this.username = username;
                  this.password = password;
              }
              public String getUsername() {
                  return username;
              }
              public void setUsername(String username) {
                  this.username = username;
              }
              public String getPassword() {
                  return password;
              }
              public void setPassword(String password) {
                  this.password = password;
              }
              public void Loginfo(String username,String password)throws UserNameException,PassWordException{
                  if(!this.username.equals(username)){
                      throw new UserNameException("用户名不存在");
                  }
                  if(!this.password.equals(password)){
                      throw new PassWordException("密码错误");
                  }
                  System.out.println("登录成功");
              }
              public static void main(String[] args) {
                  Login login = new Login();
                  while (true) {
                      try {
                          System.out.println("请输入用户名");
                          String username = new Scanner(System.in).nextLine();
                          login.setUsername(username);
                          System.out.println("请输入密码");
                          String password = new Scanner(System.in).nextLine();
                          login.setPassword(password);
                          login.Loginfo("admin","123");
                          break;
                      } catch (UserNameException e) {
                          e.printStackTrace();
                      } catch (PassWordException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }
          

转载请注明来自码农世界,本文标题:《Java学习【认识异常】》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,114人围观)参与讨论

还没有评论,来说两句吧...

Top