本文目录导读:

在Java中,断言(assert)主要用于开发和测试阶段校验程序的内部逻辑,以下是几种校验结果的常用方法和案例:
基础断言语法
public class AssertBasicExample {
public static void main(String[] args) {
int age = 25;
// 简单断言:年龄必须大于0
assert age > 0;
// 带错误信息的断言
assert age > 0 : "年龄不能小于0,当前值:" + age;
System.out.println("断言通过,年龄:" + age);
}
}
启用断言
# 启用断言(默认是关闭的) java -ea AssertBasicExample # 或 java -enableassertions AssertBasicExample # 禁用断言 java -da AssertBasicExample
实战案例:计算器校验
public class CalculatorTest {
// 除法方法
public static double divide(int dividend, int divisor) {
assert divisor != 0 : "除数不能为0";
return (double) dividend / divisor;
}
// 阶乘方法
public static int factorial(int n) {
assert n >= 0 : "阶乘参数不能为负数,当前值:" + n;
assert n <= 20 : "阶乘结果可能溢出,当前值:" + n;
if (n <= 1) return 1;
return n * factorial(n - 1);
}
public static void main(String[] args) {
// 案例1:校验除法结果
try {
double result = divide(10, 2);
System.out.println("10/2 = " + result);
// 使用断言校验结果
assert result == 5.0 : "除法结果错误,期望5.0,实际:" + result;
System.out.println("除法结果校验通过");
} catch (AssertionError e) {
System.err.println("断言失败:" + e.getMessage());
}
// 案例2:校验阶乘结果
int factResult = factorial(5);
assert factResult == 120 : "阶乘结果错误,期望120,实际:" + factResult;
System.out.println("5! = " + factResult);
// 案例3:校验输入参数(会触发断言异常)
try {
int invalidFactorial = factorial(-1); // 这里会触发断言
} catch (AssertionError e) {
System.err.println("捕获断言错误:" + e.getMessage());
}
}
}
数组操作校验
public class ArrayAssertExample {
public static int[] sortArray(int[] arr) {
// 前置条件校验
assert arr != null : "数组不能为null";
assert arr.length > 0 : "数组不能为空";
// 冒泡排序
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
// 后置条件校验:确保排序正确
for (int i = 0; i < arr.length - 1; i++) {
assert arr[i] <= arr[i + 1] : "排序错误,位置" + i + "和" + (i+1) + "未正确排序";
}
return arr;
}
public static void main(String[] args) {
int[] numbers = {5, 3, 8, 1, 9, 2};
// 排序前打印
System.out.print("排序前:");
printArray(numbers);
// 执行排序
int[] sorted = sortArray(numbers);
// 使用断言校验结果
assert sorted[0] == 1 : "最小元素应为1";
assert sorted[sorted.length - 1] == 9 : "最大元素应为9";
assert sorted.length == numbers.length : "数组长度不应改变";
// 排序后打印
System.out.print("排序后:");
printArray(sorted);
System.out.println("数组排序校验通过");
}
private static void printArray(int[] arr) {
for (int num : arr) {
System.out.print(num + " ");
}
System.out.println();
}
}
字符串处理校验
public class StringAssertExample {
public static String reverseString(String input) {
assert input != null : "输入字符串不能为null";
StringBuilder sb = new StringBuilder(input);
String reversed = sb.reverse().toString();
// 校验反转结果
assert reversed.length() == input.length() : "反转后长度不应改变";
assert !reversed.equals(input) || input.isEmpty() : "非空字符串反转后不应与原字符串相同";
return reversed;
}
public static void main(String[] args) {
// 测试反转
String original = "Hello World";
String reversed = reverseString(original);
System.out.println("原字符串:" + original);
System.out.println("反转后:" + reversed);
// 使用断言校验结果
assert reversed.equals("dlroW olleH") : "反转结果不正确";
System.out.println("字符串反转校验通过");
// 测试空字符串
String emptyReversed = reverseString("");
assert emptyReversed.isEmpty() : "空字符串反转后仍应为空";
System.out.println("空字符串处理校验通过");
// 测试null(会触发断言异常)
try {
reverseString(null);
} catch (AssertionError e) {
System.err.println("预期的断言错误:" + e.getMessage());
}
}
}
最佳实践
public class AssertBestPractices {
// 1. 私有方法中使用断言
private static int calculateInternal(int value) {
// 私有方法参数校验使用断言
assert value > 0 : "内部方法参数必须为正数";
return value * 2;
}
// 2. 永不失败的断言(用于文档说明)
public static void processData(int[] data) {
// 契约式编程中的不变式
assert data != null : "数据不能为null";
// 处理数据...
// 确保处理过程中不会改变数组长度
int originalLength = data.length;
// ... 处理逻辑
assert data.length == originalLength : "数组长度不应改变";
}
// 3. switch语句的完整性检查
public static String getDayName(int day) {
String dayName;
switch (day) {
case 1: dayName = "Monday"; break;
case 2: dayName = "Tuesday"; break;
case 3: dayName = "Wednesday"; break;
case 4: dayName = "Thursday"; break;
case 5: dayName = "Friday"; break;
case 6: dayName = "Saturday"; break;
case 7: dayName = "Sunday"; break;
default:
assert false : "无效的星期几:" + day;
dayName = "Invalid";
}
return dayName;
}
public static void main(String[] args) {
// 测试内部方法
int result = calculateInternal(5);
assert result == 10 : "计算结果应为10";
System.out.println("内部方法测试通过");
// 测试switch完整性
String monday = getDayName(1);
assert monday.equals("Monday") : "应该是Monday";
String sunday = getDayName(7);
assert sunday.equals("Sunday") : "应该是Sunday";
System.out.println("switch语句测试通过");
// 测试无效输入(会触发断言)
try {
getDayName(8); // 无效输入
} catch (AssertionError e) {
System.err.println("预期的断言错误:" + e.getMessage());
}
}
}
断言校验的关键点:
- 启用断言:
java -ea YourClass - 使用场景:开发测试阶段,不用于生产环境
- :
- 方法前置条件
- 方法后置条件
- 类不变式
- 内部逻辑一致性
- 异常处理:断言失败抛出
AssertionError,通常不捕获 - 最佳实践:
- 不用于公共方法参数校验(应使用IllegalArgumentException)
- 不用于执行程序逻辑
- 仅用于调试和测试