第29篇:Java Date 类详解
📌 系列导航:《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第28篇:Java反射机制原理详解 |
➡️ 下一篇:第30篇:Date类、Calendar类、date转calendar
一、核心知识点
java.util.Date的基本使用(Java 1.0 起)- Date 的问题:年份从1900开始、月份从0开始、可变、线程不安全
SimpleDateFormat格式化与解析(线程不安全)- 推荐使用
java.time包(Java 8+):LocalDate、LocalDateTime、ZonedDateTime、DateTimeFormatter
二、通俗讲解(1分钟开心学)
1. Date 类的缺陷
java.util.Date 是 Java 早期设计的日期类,存在很多不合理之处:
- 年份从1900开始,
new Date(2024 - 1900, 4, 6)表示2024年5月6日(月从0开始)。 - 月份从0开始,11月是10?不,11是12?非常容易混乱。
- 大部分方法已废弃(如
getYear()、setMonth())。 Date是可变的,线程不安全。- 时区处理混乱。
2. SimpleDateFormat 的线程不安全问题
SimpleDateFormat 用于格式化 Date 或解析字符串。它的内部有一个 Calendar 引用,多线程共享时,一个线程修改 Calendar 会影响其他线程,导致解析错误或异常。
3. Java 8 的 java.time 包
Java 8 引入了全新的日期时间 API,位于 java.time 包下:
LocalDate:只含日期(年月日)LocalTime:只含时间(时分秒纳秒)LocalDateTime:含日期和时间ZonedDateTime:带时区的日期时间DateTimeFormatter:线程安全的格式化器
这些类都是不可变的,线程安全,API 设计清晰。
生活类比:
Date就像一把老式门锁,能用但别扭。LocalDate是现代智能锁,直观、安全、好用。
三、实操代码案例 + 场景说明
场景:解析用户输入的生日字符串,计算年龄。
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.Date;
public class DateDemo {
public static void main(String[] args) throws Exception {
// ========== 旧API(不推荐)==========
// 1. Date 的陷阱
Date date = new Date(2024 - 1900, 4, 6); // 2024年5月6日
System.out.println(date);
// 2. SimpleDateFormat 线程不安全演示(单线程没问题,多线程要小心)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String dateStr = "2024-05-06";
Date parsed = sdf.parse(dateStr);
System.out.println(sdf.format(parsed));
// ========== 新API(推荐)==========
// 3. LocalDate 基本使用
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(2000, 5, 1); // 年,月,日 直观
System.out.println("今年生日是:" + birthday);
// 4. 日期计算(年龄)
int age = Period.between(birthday, today).getYears();
System.out.println("年龄:" + age);
// 5. 格式化(线程安全)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
String formatted = today.format(formatter);
System.out.println("格式化日期:" + formatted);
// 6. 字符串解析
LocalDate parsedDate = LocalDate.parse("2025-12-31"); // ISO格式默认支持
LocalDate customParsed = LocalDate.parse("2025/12/31", DateTimeFormatter.ofPattern("yyyy/MM/dd"));
System.out.println(customParsed);
}
}
四、避坑要点
| 错误/误区 | 后果 | 正确做法 |
|---|---|---|
使用 Date 的废弃构造方法 | 代码不清晰,容易错 | 使用 java.time 或 Calendar |
多个线程共享一个 SimpleDateFormat | 解析错误、异常 | 每次新建,或用 ThreadLocal 包装 |
| 忘记处理时区 | 时区转换错误 | 使用 ZonedDateTime 或明确时区 |
LocalDate 与 Date 混用时转换错误 | 类型不匹配 | 使用 Date.from(instant) 和 date.toInstant() |
五、面试高频考点
Q1:为什么 SimpleDateFormat 是线程不安全的?
内部维护了一个
Calendar对象,多线程同时调用format或parse时会互相干扰,导致状态错乱。
Q2:Java 8 推荐使用哪些日期时间类?
LocalDate、LocalDateTime、ZonedDateTime、DateTimeFormatter,它们不可变、线程安全、API 清晰。
Q3:如何将 java.util.Date 转换为 LocalDateTime?
Date date = new Date(); LocalDateTime ldt = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
六、练习题
- 代码改错:指出以下代码的问题并修正。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date d1 = sdf.parse("2024-01-01"); Date d2 = sdf.parse("2024-01-02"); - 编程:计算从出生日期到今天的天数(使用
java.time)。 - 简答:
LocalDate和Date的主要区别?
📊 你的学习进度
- 当前:第29篇 / 共44篇 · 第四阶段:注解、反射、代理、日期(第26~31篇)
- ✅ 已完成:第1~28篇
- 📖 正在学:第29篇
- ⏳ 待学习:第30~44篇
👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇
💡 本专栏每篇都包含:避坑表 + 面试高频考点 + 练习题。每天30分钟,100天拿offer!
下一篇文章预告
《Date类、Calendar类、date转calendar》
内容简介:Calendar的功能(add/roll区别)、Date与Calendar互转、为什么Calendar也被废弃。
💡 学完这篇,你将掌握旧版日期处理的全貌,并理解为什么必须迁移到java.time。
📌 《Java 100 天进阶之路 | 从入门到上岗就业》 每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!

1244

被折叠的 条评论
为什么被折叠?



