Java语言程序设计——篇十二


🌿🌿🌿跟随博主脚步,从这里开始→博主主页🌿🌿🌿

  • 欢迎大家:这里是我的学习笔记、总结知识的地方,喜欢的话请三连,有问题可以私信🌳🌳🌳
    您的点赞👍、关注➕、收藏⭐️、评论📝、私信📧是我最大的支持与鼓舞!!!🌻🌻🌻

异常处理

主要内容

1️⃣异常与异常类(异常是什么?Java内部提供了哪些异常类)

2️⃣异常处理(如何处理异常?)

3️⃣自定义异常类(用户自己如何定义异常类?)

4️⃣ 断言(高级的异常处理形式)

1️⃣异常与异常类

异常

  • 异常(exception)是在程序运行过程中产生的使程序终止正常运行的错误对象。
  • 如数组下标越界、整数除法中零作除数、文件找不到等都可能使程序终止运行。

异常类

  • Java定义了多种异常类。都是java.lang.Throwable类的子类,它是Object类的直接子类。
  • Throwable类有两个子类
    ① Error类
    ② Exception类

2️⃣异常处理

异常的抛出与捕获

  • 方法运行过程中如果产生了异常,在这个方法中就生成一个代表该异常类的对象,并把它交给运行时系统,运行时系统寻找相应的代码来处理该异常。这个过程称为抛出异常。
  • 运行时系统在方法的调用栈中查找,从产生异常的方法开始进行回溯,直到找到包含相应异常处理的方法为止,这一过程称为捕获异常。
  • 方法调用与回溯如图所示。

try-catch-finally语句

java 复制代码
try{
     // 需要处理的代码
} catch (ExceptionType1 exceptionObject){
    // 异常处理代码
}[catch (ExceptionType2 exceptionObject){
    // 异常处理代码
}
finally{
    // 最后处理代码
} ]

用catch捕获多个异常

  • 如果在多个catch块捕获的异常**使用相同的代码处理,**则可以仅用一个catch块处理,而不必单独捕获每个异常,这就减少了代码重复。
  • 要在一个catch语句中处理多个异常,需要使用"或"运算符(|)分隔多个异常。

声明方法抛出异常

  • 有时方法中产生的异常不需要在该方法中处理,可能需要由该方法的调用方法处理,这时可以在声明方法时用throws子句声明抛出异常,将异常传递给调用该方法的方法处理。
java 复制代码
 returnType methodName([paramlist]) 
                 throws ExceptionList{
         // 方法体
   } 

用throw语句抛出异常

  • 可以创建一个异常对象,然后用throw语句抛出,或者将捕获到的异常对象用throw语句再次抛出,throw语句的格式如下:
java 复制代码
  throw  exceptInstance;

使用try-with-resources语句

  • 在JDK 7之前,通常使用finally语句确保调用close()方法:
java 复制代码
 try{
          // 打开资源
  }catch(Exception e){
        // 处理异常
  }finally{
        // 关闭资源
  }
实战演练

下面是打开一个数据库连接的典型代码:

java 复制代码
Connection connection = null;
try{
    // 创建连接对象并执行操作
}catch(Exception e){
   // 处理异常
}finally{
   if(connection!=null){
     try{
         connection.close();
     }catch(SQLException e){  // 处理异常  }
   }
}   
  • JDK 7提供的自动关闭资源的功能为管理资源(如文件流、数据库连接等)提供了一种更加简便的方式。这种功能是通过一种新的try语句实现的,叫try-with-resources,有时称为自动资源管理。
  • try-with-resources的主要好处是可以避免在资源(如文件流)不需要时忘记将其关闭。
  • try-with-resources语句的基本形式如下:
java 复制代码
try(
        声明和创建某种资源 )//(只有实现了java.lang.AutoCloseable接口的那些资源才可自动关闭。)
{
     // 使用资源
}
 [catch(Exception  e){}]
 [finally{ 
 }]

3️⃣自定义异常

  • 编写自定义异常类实际上是继承一个标准异常类,通常继承Exception类,如下所示:
java 复制代码
 class CustomException extends Exception {   
     public CustomException(){}  
     public CustomException(String message) {  
        super(message);    
     }
  }
实战演练

问题描述:

程序中需要验证用户输入的数据值必须是正值。如果用户提供的是负值,程序抛出异常。

编写一个自定义异常类NegativeValueException,负值异常。

java 复制代码
// 自定义运行时异常类 NegativeValueException  
public class NegativeValueException extends RuntimeException {  
  
    // 可以添加一个无参构造器  
    public NegativeValueException() {  
        super("输入值不能为负!");  
    }  
  
    // 也可以添加一个带有详细错误信息的构造器  
    public NegativeValueException(String message) {  
        super(message);  
    }  
  
    // 还可以添加一个带有错误信息和原因的构造器  
    public NegativeValueException(String message, Throwable cause) {  
        super(message, cause);  
    }  
  
    // 还可以添加一个带有原因的构造器  
    public NegativeValueException(Throwable cause) {  
        super(cause);  
    }  
  
    // 根据需要,你也可以添加更多的构造器或方法  
}

然后,你可以在你的程序中使用这个异常类来验证用户输入的值。下面是一个简单的示例,展示了如何在用户输入负值时抛出NegativeValueException:

java 复制代码
import java.util.Scanner;  
  
public class Main {  
    public static void main(String[] args) {  
        Scanner scanner = new Scanner(System.in);  
  
        System.out.print("请输入一个正数: ");  
        double input = scanner.nextDouble();  
  
        try {  
            validatePositive(input);  
            System.out.println("输入有效,您输入的是: " + input);  
        } catch (NegativeValueException e) {  
            System.out.println(e.getMessage());  
        }  
  
        scanner.close();  
    }  
  
    // 验证输入是否为正数  
    public static void validatePositive(double number) throws NegativeValueException {  
        if (number < 0) {  
            throw new NegativeValueException("您输入了一个负数!");  
        }  
    }  
}

在这个示例中,validatePositive方法用于检查用户输入的值是否为正数。如果输入的是负数,它将抛出一个NegativeValueException。在main方法中,通过try-catch块捕获并处理这个异常。如果用户输入了负数,程序将输出错误消息而不是崩溃。

4️⃣断言

使用断言

  • 所谓断言(assertion)是一个Java语句,其中指定一个布尔表达式,程序员认为在程序执行时该表达式的值应该为true。
  • 程序通过计算该布尔表达式执行断言,若该表达式为false程序会报告一个错误。通过验证断言是true,能够使程序员确信程序的正确性。
  • 断言是通过assert关键字来声明的,断言的使用有两种格式:
java 复制代码
assert expression ;//如果该表达式值为false,抛出AssertionError异常
assert expression : detailMessage ;

开启和关闭断言

  • 编译带有断言的程序与一般程序相同。默认情况下,断言在运行时是关闭的,要开启断言功能,在运行程序时需要使用 --enableassertions或-ea选项,例如:

D:\study>java --ea AssertionDemo

  • 在Eclipse中要开启断言,按下列步骤操作:
    Run→ Run Configurations → 选择Arguments选项卡
    → Arguments文本框中输入--enableassertions 或-ea 然后执行程序

    何时使用断言

  • 通常来说,断言用于检查一些关键的值,并且这些值对整个应用程序或局部功能的实现有较大影响,并且当断言失败,这些错误是不容易恢复的。

  • 以下是一些使用断言的情况,它们可以使Java程序的可靠性更高。

    1. 检查控制流
      在if~else和switch~case结构中,可以在不应该发生的控制支流上加上assert false语句。如果这种情况发生了,断言就能够检查出来。
      例如,假设x的值只能取1、2或3,可以编写下面的代码:
java 复制代码
 switch (x) {
    case 1: ...;
    case 2: ...;
    case 3: ...;
    default: assert false : "x 值非法:" + x;
  }
    1. 检查前置条件(precondition)
      private修饰的方法前检查输入参数是否有效。
      例如,某方法可能要求输入的参数param不能为null,就可以在方法的开头加上下面语句:
java 复制代码
assert param != null:"参数不能为null";
    1. 检查后置条件(postcondition)
      在方法计算之后检查结果是否有效。对于一些计算方法,运行完成后,某些值需要保证一定的性质。
      例如,对计算绝对值的方法可以在方法的结束处使用下面语句进行检查:
java 复制代码
assert value >= 0:"结果应该大于等于0:" + value; 
    1. 检查程序不变量
      在程序的运行过程中这些变量的值是不变的,称为不变量。这些不变量可能是一个简单表达式,也可能是一个复杂表达式。对于一些关键的不变量,可以通过assert进行检查。
断言示例

问题描述

使用对象数组实现一个简单的栈类,在push()、pop()和topValue()方法中使用断言。

java 复制代码
public class SimpleStack<T> {  
    private Object[] elements;  
    private int size;  
    private int capacity;  
  
    public SimpleStack(int initialCapacity) {  
        capacity = initialCapacity;  
        elements = new Object[capacity];  
        size = 0;  
    }  
  
    // 向栈中添加元素  
    public void push(T item) {  
        assert size < capacity : "Stack is full, cannot push new item";  
        elements[size++] = item;  
    }  
  
    // 从栈中移除并返回顶部元素  
    @SuppressWarnings("unchecked")  
    public T pop() {  
        assert size > 0 : "Stack is empty, cannot pop item";  
        return (T) elements[--size];  
    }  
  
    // 返回栈顶元素但不移除  
    @SuppressWarnings("unchecked")  
    public T topValue() {  
        assert size > 0 : "Stack is empty, cannot access top value";  
        return (T) elements[size - 1];  
    }  
  
    // 获取栈的当前大小  
    public int getSize() {  
        return size;  
    }  
  
    // 获取栈的容量  
    public int getCapacity() {  
        return capacity;  
    }  
  
    // 为了简单起见,这里不实现扩容逻辑  
    // 在实际应用中,你可能需要在push时检查容量,并在需要时扩容  
}  
  
// 使用示例  
public class Main {  
    public static void main(String[] args) {  
        SimpleStack<Integer> stack = new SimpleStack<>(5);  
  
        stack.push(1);  
        stack.push(2);  
        stack.push(3);  
  
        System.out.println("Top value: " + stack.topValue()); // 应输出 3  
  
        stack.pop();  
        System.out.println("New top value: " + stack.topValue()); // 应输出 2  
  
        // 尝试在空栈上调用 pop() 或 topValue(),这将触发断言错误(如果启用了断言)  
        // 注意:在生产环境中,断言可能会被禁用,因此最好有额外的错误处理逻辑  
        // stack.pop(); // 这将引发 AssertionError,如果断言被启用  
    }  
}

博主用心写,读者点关注,互动传真情,只是不迷路。

相关推荐
轻口味22 分钟前
命名空间与模块化概述
开发语言·前端·javascript
苹果醋31 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
晓纪同学1 小时前
QT-简单视觉框架代码
开发语言·qt
威桑1 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
Hello.Reader1 小时前
深入解析 Apache APISIX
java·apache
飞飞-躺着更舒服1 小时前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
了一li1 小时前
Qt中的QProcess与Boost.Interprocess:实现多进程编程
服务器·数据库·qt
明月看潮生1 小时前
青少年编程与数学 02-004 Go语言Web编程 16课题、并发编程
开发语言·青少年编程·并发编程·编程与数学·goweb
明月看潮生1 小时前
青少年编程与数学 02-004 Go语言Web编程 17课题、静态文件
开发语言·青少年编程·编程与数学·goweb
Java Fans2 小时前
C# 中串口读取问题及解决方案
开发语言·c#