news 2026/5/1 10:51:53

java学习--Date

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
java学习--Date

一、核心概述:Date 类的定位与现状

✅ 核心作用

java.util.Date是 Java 中最基础的日期时间处理类,核心能力是表示一个「特定的瞬间」(精确到毫秒级别,记录从「1970 年 1 月 1 日 00:00:00 GMT」—— 即纪元时间 / 时间戳原点 到目标时刻的毫秒数)。

✅ 重要现状(必知)

Date类是 Java 初代日期 API,JDK 1.1 起就被标记为「大部分方法过时(@Deprecated)」,仅保留少数核心可用方法。

  • ❌ 过时原因:线程不安全、设计缺陷、日期计算 / 格式化操作繁琐、时区处理能力弱
  • ✅ 替代方案:JDK 1.8 推出的java.time 新日期时间 APILocalDate/LocalTime/LocalDateTime/Instant等),线程安全、设计优雅,是当前开发首选

二、Date 类核心 API 详解(分「可用」和「过时」)

✅ 1. 仍在使用的核心方法(重点掌握)

这些方法未被废弃,是 Date 类目前的核心实用能力,全部基于「时间戳(毫秒)」操作:

① 构造方法(2 个可用)
import java.util.Date; public class DateDemo { public static void main(String[] args) { // 构造1:创建【当前系统时间】的Date对象(最常用) Date now = new Date(); System.out.println("当前时间:" + now); // 构造2:根据【指定时间戳(毫秒)】创建Date对象 // 时间戳:从1970-01-01 00:00:00 GMT到目标时间的毫秒数(正数=之后,负数=之前) long timestamp = 1751234567890L; Date targetDate = new Date(timestamp); System.out.println("指定时间戳的时间:" + targetDate); } }
② 成员方法(5 个核心可用)
public class DateMethodDemo { public static void main(String[] args) { Date now = new Date(); long timestamp = 1751234567890L; Date target = new Date(timestamp); // 1. long getTime():获取当前Date对象对应的【时间戳(毫秒)】 → 最常用 long nowTime = now.getTime(); System.out.println("当前时间戳:" + nowTime); // 2. void setTime(long time):给Date对象【设置指定时间戳】,覆盖原有时间 now.setTime(timestamp); System.out.println("设置新时间戳后的now:" + now); // 3. boolean after(Date when):判断当前时间 是否【晚于】指定时间 boolean isAfter = now.after(target); System.out.println("now是否晚于target:" + isAfter); // 4. boolean before(Date when):判断当前时间 是否【早于】指定时间 boolean isBefore = now.before(target); System.out.println("now是否早于target:" + isBefore); // 5. boolean equals(Object obj):判断两个时间是否【相等】(毫秒级一致) boolean isEqual = now.equals(target); System.out.println("now是否等于target:" + isEqual); } }

❌ 2. 已过时的方法(绝对避坑)

以下方法均被@Deprecated标记,严禁在开发中使用,列举常见的废弃方法及替代方案:

废弃方法功能替代方案
int getYear()获取年份使用Calendar.get(Calendar.YEAR)或 新 APILocalDate.getYear()
int getMonth()获取月份使用Calendar.get(Calendar.MONTH)或 新 APILocalDate.getMonthValue()
int getDate()获取日期使用Calendar.get(Calendar.DATE)或 新 APILocalDate.getDayOfMonth()
void setYear(int year)设置年份使用Calendar.set(Calendar.YEAR, year)或 新 API(不可变,创建新对象)
String toLocaleString()本地化格式使用SimpleDateFormat或 新 APIDateTimeFormatter

⚠️ 关键提醒:废弃方法的设计存在严重缺陷(例如月份从 0 开始、年份偏移 1900),极易导致业务 BUG,坚决不要使用

三、Date 类的两大核心操作(格式化 + 解析)

Date 本身仅表示「时间瞬间」,无法直接控制显示格式,必须配合格式化工具类完成「格式定制」和「字符串转 Date」操作,主流方案有 2 种:

✅ 方案 1:传统工具SimpleDateFormat(JDK1.1 推出,兼容所有版本)

核心作用:格式化(Date → 自定义格式字符串)+解析(字符串 → Date),是 Date 类的「标配工具」。

完整示例代码
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class DateFormatDemo { public static void main(String[] args) throws ParseException { Date now = new Date(); // 1. 定义格式化规则(关键:模式字母对应固定含义,大小写敏感) // 常用模式:yyyy(4位年)、MM(2位月)、dd(2位日)、HH(24小时)、hh(12小时)、mm(分)、ss(秒)、SSS(毫秒) SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); // ========== 操作1:格式化(Date → 字符串) ========== String dateStr = sdf.format(now); System.out.println("格式化后的时间:" + dateStr); // 示例:2025-12-28 15:30:45 123 // ========== 操作2:解析(字符串 → Date) ========== String timeStr = "2024-07-30 10:20:30 000"; Date parseDate = sdf.parse(timeStr); // 字符串格式必须和模式完全匹配,否则抛ParseException System.out.println("解析后的Date对象:" + parseDate); // ========== 拓展:切换格式(修改模式即可) ========== SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒"); System.out.println("中文格式:" + sdf2.format(now)); // 示例:2025年12月28日 15时30分45秒 } }
⚠️ 注意事项

SimpleDateFormat线程不安全禁止在多线程环境下共享同一个实例(例如定义为全局静态变量),否则会导致日期错乱、抛出异常。

✅ 方案 2:JDK8 新工具DateTimeFormatter(推荐,线程安全)

JDK8 推出的新格式化工具,线程安全、无异常风险,是当前开发的首选方案,可无缝对接 Date 和新日期 API。

四、JDK8 新日期 API 与 Date 互转(开发必备)

✅ 核心说明

JDK8 新日期 API(java.time包)是 Java 日期处理的「终极方案」,优势如下:✅ 线程安全 ✅ 设计优雅 ✅ 支持链式调用 ✅ 时区 / 偏移量处理完善 ✅ 无废弃方法核心类:Instant(对应 Date,表示时间瞬间)、LocalDate(仅日期)、LocalTime(仅时间)、LocalDateTime(日期 + 时间)

✅ 关键互转(Date ↔ Instant ↔ LocalDateTime)

Date 和新 API 的核心桥梁是Instant(二者均表示「时间戳瞬间」),完整互转代码:

import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Date; public class DateToNewApiDemo { public static void main(String[] args) { Date nowDate = new Date(); ZoneId zoneId = ZoneId.systemDefault(); // 获取系统默认时区(例如Asia/Shanghai) // ========== 1. Date → Instant(核心桥梁) ========== Instant instant = nowDate.toInstant(); System.out.println("Date转Instant:" + instant); // ========== 2. Instant → LocalDateTime(最常用,日期+时间) ========== LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zoneId); System.out.println("Instant转LocalDateTime:" + localDateTime); // ========== 3. LocalDateTime → Instant → Date ========== Instant newInstant = localDateTime.atZone(zoneId).toInstant(); Date newDate = Date.from(newInstant); System.out.println("LocalDateTime转回Date:" + newDate); } }

五、Date 类经典面试题 & 高频坑点(必记)

✅ 面试题 1:Date 类的 getYear () 方法为什么返回值「比实际年份小 1900」?

答:这是 Date 类的历史设计缺陷,JDK1.0 中getYear()返回的是「年份偏移量」(年份 - 1900),例如 2025 年返回 125。该方法已在 JDK1.1 废弃,替代方案是Calendar.get(Calendar.YEAR)或新 APILocalDate.getYear()

✅ 面试题 2:Date 和 SimpleDateFormat 的线程安全问题?

答:

  1. Date对象本身是可变的(例如setTime()可修改内部时间),但不存在线程安全问题(仅自身属性修改,无共享资源竞争);
  2. SimpleDateFormat线程不安全,其内部的格式化核心变量未做同步,多线程共享实例会导致格式错乱、抛出ArrayIndexOutOfBoundsException。✅ 解决方案:① 每次使用新建SimpleDateFormat实例;② 使用 JDK8DateTimeFormatter(线程安全);③ 使用 ThreadLocal 绑定实例。

✅ 面试题 3:为什么推荐使用 JDK8 新日期 API 替代 Date?

答:核心 3 点:

  1. 线程安全:新 API(LocalDate/LocalDateTime 等)是「不可变对象」,无并发风险;
  2. 设计优雅:日期、时间、日期 + 时间分离,API 语义清晰(例如plusDays(7)加 7 天),避免 Date 的混乱设计;
  3. 功能完善:原生支持时区、闰年、月份计算,无需额外工具类,开发效率提升。

✅ 高频坑点总结

  1. ❌ 误用废弃方法(getYear/getMonth)导致年份 / 月份错误;
  2. ❌ SimpleDateFormat 定义为全局静态变量,多线程下出问题;
  3. ❌ 时间戳单位混淆(Date 是「毫秒」,部分第三方工具是「秒」,需 ×1000 转换);
  4. ❌ 格式化解析时,字符串格式与模式不匹配,抛出 ParseException。

六、核心知识点总结

  1. java.util.Date表示毫秒级的时间瞬间,核心是「时间戳」,JDK1.1 后大部分方法废弃;
  2. Date 本身无格式化能力,需配合SimpleDateFormat(传统)或DateTimeFormatter(推荐);
  3. Date 与 JDK8 新 API 的互转核心是Instant,结合时区ZoneId完成;
  4. 开发建议:新项目直接使用 JDK8java.time新 API,老项目兼容 Date 时,仅使用其「getTime ()/setTime ()」等未废弃方法;
  5. 关键禁忌:绝不使用 Date 的废弃方法、绝不共享 SimpleDateFormat 实例

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 4:48:20

STM32单线协议驱动WS2812B稳定性提升方案

STM32驱动WS2812B如何不“翻车”?DMASPI硬核方案实战解析你有没有遇到过这种情况:精心写好的灯效代码,下载进板子一运行,结果颜色全乱了——本该是渐变彩虹的灯带,变成了随机闪烁的“癫痫现场”?调试半天发…

作者头像 李华
网站建设 2026/5/1 4:48:27

YOLO模型镜像内置COCO预训练权重,开箱即用

YOLO模型镜像内置COCO预训练权重,开箱即用 在智能制造工厂的质检流水线上,摄像头每秒捕捉数百帧图像,系统必须在毫秒级内判断是否存在缺陷产品。传统部署方式中,工程师常常面临“模型跑不起来”的尴尬:依赖库版本冲突、…

作者头像 李华
网站建设 2026/5/1 6:14:59

Dataflow优化(一)

一、函数无优化 void top(a,b,c,d){ func_a(a,b,i1); func_b(c,i1,i2); func_c(i2,d); } 上述代码在没有任何优化的时候,top的三个子函数是串行顺序的执行的。 二、对函数进行pipeline优化 void top(a,b,c,d){ #pragram pipeline ii 1 func_a(a…

作者头像 李华
网站建设 2026/5/1 7:56:56

PyTorch安装教程GPU版:基于CUDA-v2.6镜像的一键部署方案

PyTorch-CUDA-v2.6 镜像:高效部署 GPU 加速深度学习环境的实践路径 在现代 AI 开发中,一个稳定、开箱即用的 GPU 环境几乎成了标配。然而,每当新成员加入项目、服务器更换或需要复现某项实验时,我们总会面对那个熟悉又恼人的问题…

作者头像 李华
网站建设 2026/5/1 6:52:35

YOLO与RetinaNet对比评测:谁更适合你的业务场景?

YOLO与RetinaNet对比评测:谁更适合你的业务场景? 在智能制造车间的高速流水线上,摄像头每秒捕捉上百帧图像,系统必须在毫秒级内判断零件是否存在缺陷;而在城市高空监控中心,AI需要从4K分辨率的广角画面中识…

作者头像 李华
网站建设 2026/5/1 6:50:57

YOLOv10新增Decoupled Head,精度提升的秘密

YOLOv10新增Decoupled Head,精度提升的秘密 在工业视觉系统日益智能化的今天,一个看似微小的结构改动,可能带来检测性能的显著跃升。以YOLO系列为例,从最初的单阶段实时检测框架发展至今,每一次版本迭代都在速度与精度…

作者头像 李华