🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

為什麼不推薦在 Java 項目中使用 java.util.Date?

image

前言

如果你是一名 Java 開發者,很可能在日常工作中經常見到 java.util.Date 類。但你可能也注意到,現在 Java 開發中,我們通常會避免直接使用它。為什麼會這樣呢?今天我們就來聊聊這個話題。

一、一個「歷史悠久」的類

java.util.Date 自 Java 1.0 (1996年) 就存在了,可以說它是 Java 標準庫中的「元老」了。但正如許多古老的事物一樣,它帶著當時設計的局限性:

Date date = new Date();
System.out.println(date);

(控制台輸出結果)

Mon Sep 22 09:50:24 CST 2025

看起來很簡單對吧?但問題就藏在這簡單背後。

二、設計缺陷一覽

1. 令人困惑的 API 設計

Date 類的許多方法都已經過時(deprecated),而且設計上存在很多不合理之處:

Date date = new Date();
System.out.println("當前年月日:" + LocalDate.now());
System.out.println(date.getYear());
System.out.println(date.getMonth());

(控制台輸出結果)

當前年月日:2025-09-22
125
8

看到問題了嗎?年份從 1900 年開始計算,月份從 0 開始(0 表示一月,11 表示十二月)。這種反直覺的設計很容易導致錯誤。

2. 可變性帶來的問題

Date 對象是可變的(mutable),這意味著你創建了一個 Date 對象後,它的值還可以被改變:

Date date = new Date(2025 - 1900, 8, 22);
System.out.println("原定日期: " + date);
// 某人意外地修改了這個日期的年份
date.setYear(2026 - 1900);
System.out.println("修改後的日期: " + date);

(控制台輸出結果)

原定日期: Mon Sep 22 00:00:00 CST 2025
修改後的日期: Tue Sep 22 00:00:00 CST 2026

這種可變性在多線程環境下尤其危險,容易導致難以調試的並發問題。

3. 時區處理困難

Date 實際上並不存儲時區資訊,它只是自 1970年1月1日00:00:00 GMT 以來的毫秒數。但它的 toString() 方法卻使用系統默認時區來顯示時間,這很容易造成混淆:

Date now = new Date();
System.out.println(now); // 輸出取決於你的默認時區

4. 精度限制

Date 只能精確到毫秒級別,對於需要更高精度(如微秒、納秒)的應用場景無法滿足需求。

三、一個實際案例

假設我們要計算兩個日期之間的天數差,使用 Date 會非常麻煩:

// 使用 Date 計算兩個日期相差的天數(不推薦的方式)
Date date1 = new Date(125, 8, 22);   // 2025年9月22日
Date date2 = new Date(125, 9, 22);  // 2025年10月22日

long difference = date2.getTime() - date1.getTime();
long daysBetween = difference / (1000 * 60 * 60 * 24);
System.out.println("相差天數: " + daysBetween);

(控制台輸出結果)

相差天數: 30

這段代碼不僅難以閱讀,還需要手動處理毫秒轉換,容易出錯。

四、更好的替代方案:Java 8 時間 API

自從 Java 8 (2014年) 引入了 java.time 包,我們有了現代、完善的時間日期處理 API。

1. 清晰的 API 設計

// 創建指定日期
LocalDate date = LocalDate.of(2025, 9, 22); // 2025年9月22日,直觀明瞭!
System.out.println(date);
// 獲取當前日期時間
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
// 獲取當前日期時間,帶時區
ZonedDateTime zonedNow = ZonedDateTime.now(ZoneId.of("Asia/Taipei"));
System.out.println(zonedNow);

(控制台輸出結果)

2025-09-22
2025-09-22T10:30:21.743
2025-09-22T10:30:21.744+08:00[Asia/Taipei]

2. 不可變性,線程安全

LocalDate appointment = LocalDate.of(2025, 9, 22);
// 下面的操作會返回新的對象,原對象不變
LocalDate newDate = appointment.plusDays(30);

3. 強大的計算功能

// 計算兩個日期之間的天數
LocalDate date1 = LocalDate.of(2025, 9, 22);
LocalDate date2 = LocalDate.of(2025, 10, 22);

long daysBetween = ChronoUnit.DAYS.between(date1, date2);
System.out.println("相差天數: " + daysBetween);

(控制台輸出結果)

相差天數: 30

4. 完善的時區支持

// 明確處理時區
ZonedDateTime taipeiTime = ZonedDateTime.now(ZoneId.of("Asia/Taipei"));
ZonedDateTime newYorkTime = taipeiTime.withZoneSameInstant(ZoneId.of("America/New_York"));

五、遷移建議

通常不建議,請慎重選擇。

如果你在維護老項目,看到大量的 Date 代碼,可以考慮以下遷移策略:

  1. 新代碼:一律使用 java.time 包中的類
  2. 與舊代碼交互:使用新增的轉換方法:
/**
 * 將 java.util.Date 轉換為 LocalDate
 * @param date java.util.Date
 * @return LocalDate(僅包含年月日),如果 date 為 null 返回 null
 */
public static LocalDate toLocalDate(Date date) {
    if (Objects.isNull(date)) {
        return null;
    }
    return date.toInstant()
               .atZone(ZoneId.systemDefault())
               .toLocalDate();
}

/**
 * 將 java.util.Date 轉換為 LocalDateTime
 * @param date java.util.Date
 * @return LocalDateTime(包含年月日 + 時分秒),如果 date 為 null 返回 null
 */
public static LocalDateTime toLocalDateTime(Date date) {
    if (Objects.isNull(date)) {
        return null;
    }
    return date.toInstant()
               .atZone(ZoneId.systemDefault())
               .toLocalDateTime();
}

六、總結

java.util.Date 就像是編程世界中的「古董」——它有歷史價值,但在現代開發中有更優的 API 可以替換。它的設計缺陷、線程安全問題以及難以使用的 API 都讓我們有充分的理由轉向更現代的 java.time API。

希望這篇文章能幫助你理解為什麼不推薦使用 java.util.Date,以及如何在你的項目中使用更好的替代方案。


原文出處:https://juejin.cn/post/7552824412115812403


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝15   💬8   ❤️4
655
🥈
我愛JS
📝3   💬11   ❤️7
213
🥉
AppleLily
📝1   💬4   ❤️1
71
#4
御魂
💬1  
3
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付