主题
Java异常处理与常用API完全指南
目录
- 一、异常处理体系
- 二、BigInteger大整数处理
- 三、BigDecimal精确计算
- 四、Date日期类
- 五、Calendar日历类
- 六、SimpleDateFormat日期格式化
- 七、常见面试题
- 八、实用代码片段
- 九、经典练习题
一、异常处理体系
1.1 异常概述
异常:代码出现的不正常现象,在Java中以类和对象的形式存在。
异常继承体系:
Throwable
├── Error(错误)
│ └── 相当于绝症,需要大规模重构代码
└── Exception(异常)
├── 编译时期异常
│ └── Exception及其子类(RuntimeException除外)
└── 运行时期异常
└── RuntimeException及其子类1.2 编译时期异常 vs 运行时期异常
| 特性 | 编译时期异常 | 运行时期异常 |
|---|---|---|
| 语法检查 | 语法正确,但调用方法时爆红 | 语法正确,编写时不报错 |
| 运行时机 | 必须处理后才能编译通过 | 编译通过,运行时报错 |
| 典型例子 | FileNotFoundException, IOException | NullPointerException, ArrayIndexOutOfBoundsException |
| 处理方式 | 必须处理(throws或try-catch) | 一般不处理,修改代码逻辑 |
判断方法:
- 按住
Ctrl点击异常类,查看继承体系 - 如果继承体系中有
RuntimeException→ 运行时期异常 - 如果继承体系中没有
RuntimeException→ 编译时期异常
1.3 异常处理方式
方式一:throws抛出异常
格式:
java
修饰符 返回值类型 方法名(参数列表) throws 异常类名 {
// 方法体
}特点:
- 将异常向上抛出,由调用者处理
- 可以抛出多个异常:
throws 异常1, 异常2 - 如果多个异常有继承关系,只需抛出父类异常
示例:
java
public static void insert(String s) throws FileNotFoundException {
if (!s.endsWith(".txt")) {
throw new FileNotFoundException("文件找不到");
}
System.out.println("文件处理成功");
}弊端:如果一直往上抛,可能导致一个功能的异常影响其他功能执行。
方式二:try-catch捕获异常
格式:
java
try {
// 可能出现异常的代码
} catch (异常类型 变量名) {
// 异常处理方案
e.printStackTrace(); // 打印详细异常信息
}特点:
- 捕获并处理异常,不影响后续代码执行
- 可以有多个catch块捕获不同异常
- 如果catch的异常有继承关系,可以直接catch父类异常
示例:
java
public static void main(String[] args) {
String s = "abc.txt1";
try {
insert(s);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("删除功能");
System.out.println("修改功能");
System.out.println("查询功能");
}多个catch块
java
try {
// 可能出现多种异常的代码
} catch (IOException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}1.4 finally关键字
作用:不管是否捕获到异常,finally块中的代码都会执行。
格式:
java
try {
// 可能出现异常的代码
} catch (异常类型 变量名) {
// 异常处理
} finally {
// 一定会执行的代码
}使用场景:
- 释放资源(IO流、数据库连接、Socket等)
- 清理工作
示例:
java
public static int method() {
try {
String s = null;
System.out.println(s.length());
return 2;
} catch (Exception e) {
return 1;
} finally {
System.out.println("我一定要执行");
}
}注意:即使try或catch中有return语句,finally也会在return之前执行。
1.5 异常处理注意事项
子类重写方法时的异常抛出规则:
- 父类方法抛异常 → 子类重写后可抛可不抛
- 父类方法没抛异常 → 子类重写后不能抛异常
throws和try-catch的使用时机:
- 如果处理异常后想让后续代码正常执行 → 使用try-catch
- 如果方法之间是递进调用关系 → 可以先throws,最后统一try-catch处理
1.6 打印异常信息的三个方法
Throwable类的方法:
| 方法 | 说明 | 示例输出 |
|---|---|---|
String toString() | 返回异常类型和异常信息 | java.io.FileNotFoundException: 文件找不到 |
String getMessage() | 获取异常信息 | 文件找不到 |
void printStackTrace() | 获取最详细的异常信息(包括堆栈跟踪) | 完整的异常堆栈信息 |
推荐使用:printStackTrace() - 信息最详细,便于调试。
二、BigInteger大整数处理
2.1 BigInteger概述
作用:处理超出long类型范围的超大整数。
可表示范围:理论上无限大(受内存限制)。
2.2 BigInteger使用
构造方法:
java
BigInteger(String val)字符串内容必须是数字格式。
常用方法:
| 方法 | 说明 |
|---|---|
BigInteger add(BigInteger val) | 加法 |
BigInteger subtract(BigInteger val) | 减法 |
BigInteger multiply(BigInteger val) | 乘法 |
BigInteger divide(BigInteger val) | 除法 |
int intValue() | 转换为int |
long longValue() | 转换为long |
示例:
java
BigInteger b1 = new BigInteger("12121212121212121212121212121212121");
BigInteger b2 = new BigInteger("12121212121212121212121212121212121");
BigInteger sum = b1.add(b2);
BigInteger diff = b1.subtract(b2);
BigInteger product = b1.multiply(b2);
BigInteger quotient = b1.divide(b2);
System.out.println("加法结果: " + sum);
System.out.println("减法结果: " + diff);
System.out.println("乘法结果: " + product);
System.out.println("除法结果: " + quotient);三、BigDecimal精确计算
3.1 BigDecimal概述
作用:解决float和double类型直接参与运算时出现的精度损失问题。
问题示例:
java
float a = 3.55F;
float b = 2.12F;
float sum = a + b;
System.out.println(sum); // 输出: 5.6699998,而非预期的5.673.2 BigDecimal使用
构造方法:
java
BigDecimal(String val)推荐创建方式:
java
static BigDecimal valueOf(double val)常用方法:
| 方法 | 说明 |
|---|---|
BigDecimal add(BigDecimal val) | 加法 |
BigDecimal subtract(BigDecimal val) | 减法 |
BigDecimal multiply(BigDecimal val) | 乘法 |
BigDecimal divide(BigDecimal val) | 除法(除不尽会报错) |
BigDecimal divide(BigDecimal divisor, int scale, RoundingMode mode) | 除法(指定精度和舍入方式) |
RoundingMode舍入模式:
UP:向上加1DOWN:直接舍去HALF_UP:四舍五入
示例:
java
BigDecimal b1 = BigDecimal.valueOf(3.55);
BigDecimal b2 = BigDecimal.valueOf(2.12);
BigDecimal sum = b1.add(b2);
System.out.println("加法: " + sum); // 5.67
BigDecimal diff = b1.subtract(b2);
System.out.println("减法: " + diff); // 1.43
BigDecimal product = b1.multiply(b2);
System.out.println("乘法: " + product);
BigDecimal quotient = b1.divide(b2, 2, RoundingMode.HALF_UP);
System.out.println("除法(保留2位小数,四舍五入): " + quotient);注意:除法如果除不尽且未指定精度和舍入模式,会抛出ArithmeticException。
四、Date日期类
4.1 Date概述
作用:表示特定的瞬间,精确到毫秒。
时间常识:
- 1秒 = 1000毫秒
- 北京时区:东八区(东经116.20,北纬39.56)
- 时间原点:1970年1月1日 0时0分0秒(Unix纪元)
4.2 Date使用
构造方法:
| 构造方法 | 说明 |
|---|---|
Date() | 根据当前系统时间创建Date对象 |
Date(long time) | 根据指定毫秒值创建Date对象(从时间原点开始计算) |
常用方法:
| 方法 | 说明 |
|---|---|
void setTime(long time) | 设置时间(毫秒值) |
long getTime() | 获取时间对应的毫秒值 |
示例:
java
Date date1 = new Date();
System.out.println("当前时间: " + date1);
Date date2 = new Date(1000L);
System.out.println("时间原点后1秒: " + date2);
date1.setTime(2000L);
System.out.println("设置后的时间: " + date1);
long millis = date2.getTime();
System.out.println("毫秒值: " + millis);五、Calendar日历类
5.1 Calendar概述
特点:抽象类,用于操作日历字段。
获取对象:
java
static Calendar getInstance()5.2 Calendar使用
常用方法:
| 方法 | 说明 |
|---|---|
int get(int field) | 返回给定日历字段的值 |
void set(int field, int value) | 将给定日历字段设置为指定值 |
void add(int field, int amount) | 为给定日历字段添加或减去指定时间量 |
Date getTime() | 将Calendar转换为Date对象 |
void set(int year, int month, int date) | 设置年月日 |
重要提示:Calendar中的月份从0开始计算(0=一月,1=二月,...,11=十二月)。
日历字段常量:
Calendar.YEAR- 年Calendar.MONTH- 月Calendar.DATE/Calendar.DAY_OF_MONTH- 日Calendar.HOUR- 小时(12小时制)Calendar.HOUR_OF_DAY- 小时(24小时制)Calendar.MINUTE- 分钟Calendar.SECOND- 秒
示例:
java
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1; // 注意:需要+1
int day = calendar.get(Calendar.DATE);
System.out.println("当前日期: " + year + "-" + month + "-" + day);
calendar.set(Calendar.YEAR, 2000);
System.out.println("设置年份后: " + calendar.get(Calendar.YEAR));
calendar.add(Calendar.YEAR, -1);
System.out.println("减1年后: " + calendar.get(Calendar.YEAR));
Date date = calendar.getTime();
System.out.println("转换为Date: " + date);5.3 实用案例:计算某年2月有多少天
java
public static int getDaysOfFebruary(int year) {
Calendar calendar = Calendar.getInstance();
calendar.set(year, 2, 1); // 设置为3月1日(月份从0开始)
calendar.add(Calendar.DATE, -1); // 减1天,得到2月最后一天
return calendar.get(Calendar.DATE);
}
public static void main(String[] args) {
System.out.println("2000年2月有" + getDaysOfFebruary(2000) + "天"); // 29天
System.out.println("2001年2月有" + getDaysOfFebruary(2001) + "天"); // 28天
}六、SimpleDateFormat日期格式化
6.1 SimpleDateFormat概述
作用:
- 将Date对象按照指定格式格式化为字符串
- 将符合格式的字符串解析为Date对象
构造方法:
java
SimpleDateFormat(String pattern)6.2 格式化模式
| 字母 | 含义 | 示例 |
|---|---|---|
| y | 年 | yyyy → 2025 |
| M | 月 | MM → 01-12 |
| d | 日 | dd → 01-31 |
| H | 时(24小时制) | HH → 00-23 |
| h | 时(12小时制) | hh → 01-12 |
| m | 分 | mm → 00-59 |
| s | 秒 | ss → 00-59 |
| E | 星期 | E → 星期五 |
常用模式:
yyyy-MM-dd→ 2025-01-24yyyy-MM-dd HH:mm:ss→ 2025-01-24 15:30:45yyyy年MM月dd日 E→ 2025年01月24日 星期五
6.3 SimpleDateFormat使用
常用方法:
| 方法 | 说明 |
|---|---|
String format(Date date) | 将Date格式化为字符串 |
Date parse(String source) | 将字符串解析为Date |
示例:
java
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date now = new Date();
String dateStr = sdf.format(now);
System.out.println("格式化后的日期: " + dateStr);
String str = "2025-01-24 15:30:00";
Date parsedDate = sdf.parse(str);
System.out.println("解析后的Date: " + parsedDate);七、常见面试题
⭐ 基础题
1. 编译时期异常和运行时期异常的区别?
答案:
- 编译时期异常:语法正确,但调用方法时编译器强制要求处理。必须使用throws或try-catch处理才能编译通过。例如:FileNotFoundException、IOException。
- 运行时期异常:语法正确,编译时不报错,运行时才抛出。通常是代码逻辑错误导致,一般不需要显式处理,而是修改代码。例如:NullPointerException、ArrayIndexOutOfBoundsException。
2. throws和throw的区别?
答案:
- throws:用在方法声明处,表示该方法可能抛出的异常,将异常抛给调用者处理。
- throw:用在方法体内,用于手动创建并抛出一个异常对象。
java
public void method() throws IOException {
throw new IOException("手动抛出异常");
}3. finally块什么时候会执行?
答案: finally块无论是否捕获到异常都会执行。即使try或catch块中有return语句,finally也会在return之前执行。
特殊情况:如果在try或catch块中执行了System.exit(0),finally不会执行。
4. try-catch-finally的执行顺序?
答案:
- 执行try块
- 如果try块出现异常,执行对应的catch块
- 无论是否出现异常,都执行finally块
- 如果try或catch中有return,先执行finally,再执行return
⭐⭐ 进阶题
5. 如何选择使用throws还是try-catch?
答案:
- 使用try-catch:如果处理异常后,希望后续代码继续执行。
- 使用throws:如果方法之间是递进调用关系,可以先throws,在最后统一用try-catch处理。
- 实际开发:通常在业务逻辑层使用throws,在控制层或界面层使用try-catch统一处理。
6. 为什么float和double运算会丢失精度?如何解决?
答案: 原因:float和double采用IEEE 754浮点数标准,某些十进制小数无法精确表示为二进制浮点数,导致精度损失。
解决方案:使用BigDecimal类进行精确计算。
java
float a = 0.1f;
float b = 0.2f;
System.out.println(a + b); // 0.30000001
BigDecimal b1 = BigDecimal.valueOf(0.1);
BigDecimal b2 = BigDecimal.valueOf(0.2);
System.out.println(b1.add(b2)); // 0.37. Calendar类中月份为什么要+1?
答案: Calendar类中月份从0开始计算(0=一月,1=二月,...,11=十二月),这是设计上的历史原因。使用时需要:
- 获取月份时:
calendar.get(Calendar.MONTH) + 1 - 设置月份时:
calendar.set(Calendar.MONTH, 实际月份 - 1)
8. SimpleDateFormat是线程安全的吗?如何解决?
答案: SimpleDateFormat不是线程安全的,因为它在格式化过程中使用了实例变量来存储中间结果。
解决方案:
- 每次使用时创建新实例
- 使用ThreadLocal
- 使用JDK 8引入的DateTimeFormatter(线程安全)
⭐⭐⭐ 高级题
9. 子类重写父类方法时,异常抛出有什么限制?
答案:
- 父类方法抛出异常 → 子类重写方法可以抛出相同异常或其子类异常,也可以不抛出异常
- 父类方法没有抛出异常 → 子类重写方法不能抛出编译时期异常(可以抛出运行时期异常)
原因:多态调用时,父类引用指向子类对象,编译器只看父类方法的异常声明。
10. 如何自定义异常?
答案:
- 继承Exception或RuntimeException
- 提供构造方法
java
public class MyException extends Exception {
public MyException() {
super();
}
public MyException(String message) {
super(message);
}
}
public class MyRuntimeException extends RuntimeException {
public MyRuntimeException() {
super();
}
public MyRuntimeException(String message) {
super(message);
}
}使用场景:
- 继承Exception → 编译时期异常,强制调用者处理
- 继承RuntimeException → 运行时期异常,不强制处理
11. try-with-resources语法是什么?有什么优势?
答案: JDK 7引入的语法,用于自动关闭实现了AutoCloseable接口的资源。
java
try (FileInputStream fis = new FileInputStream("test.txt")) {
// 使用资源
} catch (IOException e) {
e.printStackTrace();
}
// 资源会自动关闭,无需finally优势:
- 代码简洁,无需手动关闭资源
- 自动处理资源关闭时的异常
- 确保资源一定会被关闭
12. 异常链(异常转译)是什么?如何实现?
答案: 异常链是指捕获一个异常后,抛出另一个异常,但保留原始异常信息。
java
try {
// 可能抛出IOException
} catch (IOException e) {
throw new MyException("业务处理失败", e); // 保留原始异常
}使用场景:
- 分层架构中,将底层异常转换为业务异常
- 隐藏实现细节,提供更友好的异常信息
八、实用代码片段
8.1 异常处理最佳实践
java
public class ExceptionDemo {
public void processFile(String filePath) {
FileInputStream fis = null;
try {
fis = new FileInputStream(filePath);
// 处理文件
} catch (FileNotFoundException e) {
System.err.println("文件未找到: " + e.getMessage());
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void processFileJava7(String filePath) {
try (FileInputStream fis = new FileInputStream(filePath)) {
// 处理文件
} catch (IOException e) {
System.err.println("IO异常: " + e.getMessage());
e.printStackTrace();
}
}
}8.2 BigDecimal工具类
java
public class BigDecimalUtil {
private static final int DEF_DIV_SCALE = 10;
public static double add(double v1, double v2) {
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.add(b2).doubleValue();
}
public static double subtract(double v1, double v2) {
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.subtract(b2).doubleValue();
}
public static double multiply(double v1, double v2) {
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.multiply(b2).doubleValue();
}
public static double divide(double v1, double v2) {
return divide(v1, v2, DEF_DIV_SCALE);
}
public static double divide(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("精度必须大于等于0");
}
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
}
}8.3 日期工具类
java
public class DateUtil {
private static final String DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss";
public static String format(Date date) {
return format(date, DEFAULT_PATTERN);
}
public static String format(Date date, String pattern) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
return sdf.format(date);
}
public static Date parse(String dateStr) throws ParseException {
return parse(dateStr, DEFAULT_PATTERN);
}
public static Date parse(String dateStr, String pattern) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
return sdf.parse(dateStr);
}
public static int getDaysBetween(Date start, Date end) {
long diff = end.getTime() - start.getTime();
return (int) (diff / (1000 * 60 * 60 * 24));
}
public static Date addDays(Date date, int days) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.DATE, days);
return calendar.getTime();
}
}九、经典练习题
基础题
1. 异常捕获练习
编写一个程序,要求用户输入一个整数,如果输入的不是整数,捕获异常并提示重新输入。
java
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
try {
System.out.print("请输入一个整数: ");
int num = Integer.parseInt(scanner.nextLine());
System.out.println("你输入的整数是: " + num);
break;
} catch (NumberFormatException e) {
System.out.println("输入格式错误,请重新输入!");
}
}
scanner.close();
}2. BigDecimal计算练习
编写程序计算圆的面积,要求精确到小数点后2位。
java
public static void main(String[] args) {
double radius = 5.5;
double area = calculateCircleArea(radius);
System.out.println("半径为" + radius + "的圆面积是: " + area);
}
public static double calculateCircleArea(double radius) {
BigDecimal r = BigDecimal.valueOf(radius);
BigDecimal pi = BigDecimal.valueOf(Math.PI);
BigDecimal area = r.multiply(r).multiply(pi);
return area.setScale(2, RoundingMode.HALF_UP).doubleValue();
}3. Date和SimpleDateFormat练习
编写程序,将当前日期格式化为"2025年01月24日 星期五"的格式。
java
public static void main(String[] args) {
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 E");
String dateStr = sdf.format(now);
System.out.println(dateStr);
}进阶题
4. 计算两个日期之间的天数
编写程序,输入两个日期字符串(格式:yyyy-MM-dd),计算它们之间相差多少天。
java
public static void main(String[] args) throws ParseException {
String date1 = "2025-01-01";
String date2 = "2025-01-24";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = sdf.parse(date1);
Date d2 = sdf.parse(date2);
long diff = Math.abs(d2.getTime() - d1.getTime());
int days = (int) (diff / (1000 * 60 * 60 * 24));
System.out.println("相差" + days + "天");
}5. 判断某年是否为闰年
使用Calendar类判断某年是否为闰年。
java
public static boolean isLeapYear(int year) {
return getDaysOfFebruary(year) == 29;
}
public static int getDaysOfFebruary(int year) {
Calendar calendar = Calendar.getInstance();
calendar.set(year, 2, 1);
calendar.add(Calendar.DATE, -1);
return calendar.get(Calendar.DATE);
}
public static void main(String[] args) {
System.out.println("2000年是闰年吗? " + isLeapYear(2000));
System.out.println("2001年是闰年吗? " + isLeapYear(2001));
System.out.println("2024年是闰年吗? " + isLeapYear(2024));
}6. 自定义异常练习
编写一个用户注册程序,要求:
- 用户名长度3-10位
- 密码长度6-15位
- 年龄18-100岁 如果不满足条件,抛出自定义异常。
java
class RegisterException extends Exception {
public RegisterException(String message) {
super(message);
}
}
public class RegisterDemo {
public static void register(String username, String password, int age)
throws RegisterException {
if (username.length() < 3 || username.length() > 10) {
throw new RegisterException("用户名长度必须在3-10位之间");
}
if (password.length() < 6 || password.length() > 15) {
throw new RegisterException("密码长度必须在6-15位之间");
}
if (age < 18 || age > 100) {
throw new RegisterException("年龄必须在18-100岁之间");
}
System.out.println("注册成功!");
}
public static void main(String[] args) {
try {
register("张三", "123456", 25);
} catch (RegisterException e) {
System.out.println("注册失败: " + e.getMessage());
}
}
}挑战题
7. 实现一个简单的日志记录器
要求:
- 记录时间戳、日志级别、日志内容
- 日志级别:INFO、WARN、ERROR
- 将日志写入文件
- 使用异常处理确保资源正确关闭
java
enum LogLevel {
INFO, WARN, ERROR
}
class Logger {
private String logFile;
public Logger(String logFile) {
this.logFile = logFile;
}
public void log(LogLevel level, String message) {
String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
String logLine = String.format("[%s] [%s] %s%n", timestamp, level, message);
try (FileWriter fw = new FileWriter(logFile, true);
BufferedWriter bw = new BufferedWriter(fw)) {
bw.write(logLine);
} catch (IOException e) {
System.err.println("日志写入失败: " + e.getMessage());
}
}
}
public class LoggerDemo {
public static void main(String[] args) {
Logger logger = new Logger("app.log");
logger.log(LogLevel.INFO, "应用程序启动");
logger.log(LogLevel.WARN, "内存使用率较高");
logger.log(LogLevel.ERROR, "数据库连接失败");
}
}8. 日期计算器
编写一个日期计算器,支持以下功能:
- 计算两个日期之间的天数
- 计算指定日期N天后的日期
- 计算指定日期N天前的日期
- 判断某天是星期几
java
public class DateCalculator {
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public static int daysBetween(String date1, String date2) throws ParseException {
Date d1 = sdf.parse(date1);
Date d2 = sdf.parse(date2);
long diff = Math.abs(d2.getTime() - d1.getTime());
return (int) (diff / (1000 * 60 * 60 * 24));
}
public static String addDays(String date, int days) throws ParseException {
Calendar calendar = Calendar.getInstance();
calendar.setTime(sdf.parse(date));
calendar.add(Calendar.DATE, days);
return sdf.format(calendar.getTime());
}
public static String getWeekDay(String date) throws ParseException {
String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
Calendar calendar = Calendar.getInstance();
calendar.setTime(sdf.parse(date));
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
return weekDays[dayOfWeek];
}
public static void main(String[] args) throws ParseException {
String date1 = "2025-01-01";
String date2 = "2025-12-31";
System.out.println("相差天数: " + daysBetween(date1, date2));
System.out.println("100天后: " + addDays(date1, 100));
System.out.println("100天前: " + addDays(date1, -100));
System.out.println("星期: " + getWeekDay(date1));
}
}学习建议
重点掌握
- ⭐⭐⭐ 异常处理机制(try-catch-finally)
- ⭐⭐⭐ throws和throw的区别
- ⭐⭐⭐ BigDecimal解决精度问题
- ⭐⭐ SimpleDateFormat日期格式化
- ⭐⭐ Calendar日历操作
学习路径
- 理解异常体系结构
- 掌握异常处理的两种方式
- 熟练使用BigDecimal进行精确计算
- 掌握Date、Calendar、SimpleDateFormat的使用
- 通过练习题巩固知识
常见误区
- ❌ 混淆throws和throw的作用
- ❌ 忘记Calendar月份从0开始
- ❌ 使用double直接进行金额计算
- ❌ 忘记关闭IO资源
- ❌ SimpleDateFormat线程安全问题
实践建议
- 多写异常处理的代码,理解执行流程
- 使用BigDecimal处理金额相关的计算
- 封装日期工具类,提高代码复用性
- 阅读JDK源码,理解异常体系设计
- 关注JDK 8新日期API(LocalDate、LocalDateTime)