日期:2026-07-28
项目:c260728
作者:WanJL
异常(Exception) 就是程序出现不正常的情况。
在 Java 中,异常和错误都继承自 Throwable 类:
Throwable(顶级父类)
├── Exception(异常类 — 程序本身可以处理的问题)
│ ├── RuntimeException(运行时异常)
│ │ ├── ArithmeticException(算术异常,如除零)
│ │ ├── ArrayIndexOutOfBoundsException(数组下标越界)
│ │ ├── NullPointerException(空指针异常)
│ │ └── ...
│ └── 非 RuntimeException(编译期异常 — 编译时必须处理)
│ ├── IOException
│ ├── SQLException
│ └── ...
└── Error(错误类 — 严重问题,代码无法处理)
├── StackOverflowError(栈溢出,如无限制递归)
├── OutOfMemoryError(内存溢出)
└── ...
📄 来源:
Demo01.java
核心要点:
Exception 及其子类可以被我们捕获处理或抛出,是程序可以处理的问题。Error 是内存级别的严重问题,不是我们可以捕获抛出的,需要改代码。Exception 类或其子类,才可以被我们捕获处理或抛出。| 类型 | 说明 | 示例 |
|---|---|---|
| 编译期异常(Checked Exception) | 编译时就会报错,必须处理(捕获/抛出)才能通过编译 | IOException, SQLException |
| 运行时异常(Runtime Exception) | 编译时不报错,运行后才报错。所有运行时异常的父类是 RuntimeException |
ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException |
Java 程序执行流程:
.java(源代码) ---[javac 编译]---> .class(字节码) ---[java 解释]---> 运行结果
编译期 运行期
📄 来源:
Demo01.java
如果程序出了问题,我们不做任何处理,最终会由 JVM 做默认处理,处理步骤:
📄 来源:
Demo01.java
try {
// 可能出现异常的代码
} catch (异常类型1 变量名) {
// 异常类型1的处理方式
} catch (异常类型2 变量名) {
// 异常类型2的处理方式
} catch (异常类型n 变量名) {
// 异常类型n的处理方式
}
catch 块遵循 从上到下匹配 的原则int a = 0;
try {
int[] arr = {};
arr[3] = 5; // 数组下标越界 → ArrayIndexOutOfBoundsException
} catch (ArithmeticException e) {
System.out.println("不能除以0");
System.out.println("以及一些其他的异常处理操作.....");
} catch (RuntimeException e) {
System.out.println("出现了运行时异常");
} catch (Exception e) {
System.out.println("出现了异常..但不是运行时异常");
}
System.out.println(a);
System.out.println("........后续的代码正在运行................");
📄 来源:
Demo01.java
输出结果分析: 由于 arr[3] = 5 抛出的是 ArrayIndexOutOfBoundsException,它是 RuntimeException 的子类,因此会被第二个 catch 块捕获,输出"出现了运行时异常",然后程序继续执行后续代码。
我们不处理异常,交给调用者去处理。如果方法内包含编译期异常,可以不在方法内处理,只使用 throws 抛出:
最终抛给 JVM,JVM 进行默认的处理
public void method() throws IOException {
// 方法体中的编译期异常不处理,交给调用者
}
📄 来源:
Demo01.java(概念说明)
📄 来源:
Demo01.java
给定有前后空格和重复项的字符串数据 " 张三, 李四, 王五, 赵六, 张三, 钱七 ",需要:
| 方法 | 说明 |
|---|---|
String.split(String regex) |
按指定正则表达式分割字符串为字符串数组 |
String.trim() |
去除字符串前后的空白字符 |
Arrays.toString(Object[] a) |
将数组转换为字符串表示形式 |
String data = " 张三, 李四, 王五, 赵六, 张三, 钱七 ";
// 第一步:分割 + 去空格
String[] split = data.split(",");
for (int i = 0; i < split.length; i++) {
split[i] = split[i].trim();
}
// 第二步:统计不重复元素个数
int count = 0;
for (int i = 0; i < split.length; i++) {
boolean b = false;
for (int j = 0; j < i; j++) {
if (split[i].equals(split[j])) {
b = true;
break;
}
}
if (b == false) {
count++;
}
}
// 第三步:创建新数组,放入不重复元素
String[] newArr = new String[count];
int index = 0;
for (int i = 0; i < split.length; i++) {
boolean b = false;
for (int j = 0; j < i; j++) {
if (split[i].equals(split[j])) {
b = true;
break;
}
}
if (b == false) {
newArr[index] = split[i];
index++;
}
}
for (int i = 0; i < newArr.length; i++) {
int count02 = 0;
for (int j = 0; j < split.length; j++) {
if (newArr[i].equals(split[j])) {
count02++;
}
}
System.out.println(newArr[i] + ":" + count02 + "次");
}
📄 来源:
StringUtilTest.java
关键知识点:
split[i].equals(split[j]) — 字符串比较使用 equals(),不能使用 ==boolean b)实现去重计算当前日期距离 2026-12-31 还有多少天。
| 方法 | 说明 |
|---|---|
LocalDate.of(int year, int month, int dayOfMonth) |
创建指定日期的 LocalDate 对象 |
LocalDate.toEpochDay() |
返回从 1970-01-01 到当前日期的天数 |
LocalDate localDate = LocalDate.of(2026, 7, 27);
LocalDate localDate2 = LocalDate.of(2026, 12, 31);
long now = localDate.toEpochDay(); // 距离 1970-01-01 有多少天
long epochDay = localDate2.toEpochDay(); // 距离 1970-01-01 有多少天
System.out.println("距离 2026-12-31 还有:" + (epochDay - now) + "天");
📄 来源:
DataMathTest.java
输出结果: 距离 2026-12-31 还有:157 天
关键知识点:
toEpochDay() 返回的是 long 类型,表示从 1970-01-01(Epoch)到当前日期的天数LocalDate.until(ChronoUnit.DAYS) 或 Period.between() 实现Throwable → Exception → RuntimeException 的继承体系try-catch 多 catch 块的写法,注意异常类型顺序(子类→父类)JVM 默认处理异常的方式(打印信息 + 终止程序)split(",") 分割带分隔符的字符串trim() 去除字符串前后空格equals() 在字符串比较中的必要性LocalDate.of() 创建指定日期toEpochDay() 计算两个日期之间的天数差until()、Period.between()、ChronoUnit.DAYS.between()Exception 或 RuntimeException 创建业务异常Period 与 Duration — Java 8 日期时间 API 中更灵活的时间间隔计算LinkedHashSet 去重 — 利用集合类简化去重操作(替代手动数组去重)