2009-10-15 27 views
54

Vì hầu hết mọi người đều nhận thức rõ về thời điểm hiện tại, API Java để xử lý các ngày theo lịch (cụ thể là các lớp java.util.Datejava.util.Calendar) là một mớ hỗn độn khủng khiếp.Tại sao API ngày Java (java.util.Date, .Calendar) là một mớ hỗn độn như vậy?

Off đỉnh đầu của tôi:

  • ngày là có thể thay đổi
  • ngày đại diện cho một dấu thời gian, không phải là một ngày
  • không có cách nào dễ dàng để chuyển đổi giữa các thành phần ngày (ngày, tháng, năm .. .) và ngày
  • Lịch thiếu uyển chuyển để sử dụng, và cố gắng kết hợp các hệ thống lịch khác nhau vào một lớp

This post tổng hợp nó khá tốt, và JSR-310 cũng làm lộ những vấn đề này.

Bây giờ câu hỏi của tôi là:

Các lớp này biến nó thành Java SDK như thế nào? Hầu hết các vấn đề này dường như khá rõ ràng (đặc biệt là Ngày có thể thay đổi) và nên dễ tránh. Vậy làm thế nào nó xảy ra? Áp lực thời gian? Hay là những vấn đề hiển nhiên khi nhìn lại?

Tôi nhận thấy đây không phải là một câu hỏi lập trình nghiêm ngặt, nhưng tôi thấy thú vị khi hiểu cách thiết kế API có thể bị sai. Xét cho cùng, những sai lầm luôn là một cơ hội học tập tốt (và tôi tò mò).

+1

Tiêu cực kép luôn là biểu mẫu không đúng ... Ngày không thể thay đổi được Ngày không phải là không thay đổi. –

+2

Hy vọng rằng, API ngày và giờ mới của JSR-310, dựa trên Joda-Time, sẽ xuất xưởng trong Java 7. –

+4

Và DateFormat không được thiết kế để an toàn chỉ ... (http://bugs.sun.com /bugdatabase/view_bug.do?bug_id=4093418) – Arjan

Trả lời

40

Có người đặt nó tốt hơn tôi bao giờ có thể nói nó:

  • Lớp Date đại diện cho một khoảnh khắc đặc biệt trong thời gian, với millisecond chính xác. Thiết kế của lớp này là một trò đùa rất tệ - một ví dụ điển hình về cách các lập trình viên giỏi lập trình. Hầu hết các phương thức trong Ngày hiện không được chấp nhận, được thay thế bằng các phương thức trong các lớp bên dưới.
  • Lớp Calendar là lớp trừu tượng để chuyển đổi giữa đối tượng Date và một tập hợp các trường số nguyên như năm, tháng, ngày và giờ.

  • Lớp GregorianCalendar là phân lớp duy nhất của Calendar trong JDK. Chuyển đổi Date-to-fields cho hệ thống lịch trong sử dụng phổ biến.Sun đã cấp phép cho chiếc rác quá tải này từ Taligent - một ví dụ nghiêm túc về cách các lập trình viên trung bình tăng lên.

từ Java Lập trình viên FAQ, phiên bản từ 07.X.1998, Peter van der Linden - phần này đã bị xóa khỏi các phiên bản sau mặc dù.

Vì tính có thể thay đổi, rất nhiều các lớp JDK đầu tiên gặp phải (Point, Rectangle, Dimension, ...). Tối ưu hóa sai lệch, tôi đã nghe một số người nói.

Ý tưởng là bạn muốn có thể sử dụng lại các đối tượng (o.getPosition().x += 5) thay vì tạo bản sao (o.setPosition(o.getPosition().add(5, 0))) như bạn phải làm với bất biến. Điều này thậm chí có thể là một ý tưởng tốt với các máy ảo đầu tiên, trong khi đó rất có thể là không phải với các máy ảo hiện đại.

+1

Các lớp hình học có thể thay đổi và một số có trường công cộng vì rất nhiều tham số được tạo bởi Swing và ngược lại ở đầu này là một hack để cải thiện hiệu suất. –

+3

Tôi thích báo giá. – Davie

+1

@mP, đã cập nhật bài đăng của tôi để bao gồm điều này. – gustafc

20

API ban đầu của Java không gì khác ngoài sản phẩm thời gian của chúng. Tính bất biến chỉ trở thành một năm khái niệm phổ biến sau đó. Bạn nói rằng bất biến là "hiển nhiên". Điều đó có thể đúng ngay bây giờ nhưng không phải lúc đó. Cũng giống như tiêm phụ thuộc bây giờ là "hiển nhiên" nhưng không phải 10 năm trước.

Cũng tốn thời gian để tạo đối tượng Lịch.

Chúng vẫn theo cách đó vì các lý do tương thích ngược. Có lẽ điều đáng tiếc hơn là một khi sai lầm đã được thực hiện, lớp cũ không được chấp nhận và các lớp ngày/giờ mới được tạo cho tất cả các API tiếp theo. Điều này đã đến một mức độ xảy ra với việc chấp nhận JDK 8 của một JodaTime như API (java.time, JSR 310) nhưng thực sự nó quá ít quá muộn.

+1

Ngày có trước Lịch bởi nhiều bản phát hành. Ngày đã có từ đầu và không thể xóa dễ dàng. Lịch đã được thêm vì Ngày không đầy đủ. –

8

Thời gian không dễ để đo lường và xử lý. Chỉ cần nhìn vào chiều dài của bài viết wikipedia khoảng time. Và sau đó, có những hiểu biết khác nhau về thời gian chính nó: một điểm thời gian absoulte (như một hằng số), một thời điểm tại một địa điểm nhất định, một phạm vi thời gian, độ phân giải của thời gian ...

Tôi nhớ, khi tôi đã thấy java.util.Date lần đầu tiên (JDK 1.0?) tôi là thực sự là vui vì điều đó. Các ngôn ngữ tôi biết không có một tính năng như vậy. Tôi không nghĩ về việc chuyển đổi thời gian, vv ..

Tôi nghĩ rằng nó lộn xộn, bởi vì mọi thứ thay đổi sẽ trở thành mớ hỗn độn nếu bạn phát triển từ một mức độ hiểu biết (XMLGregorianCaldender vs. Date) và yêu cầu (Nanoseconds, 2030) cấp cao hơn, nhưng giữ cho cái cũ bị ảnh hưởng. Và java.util.Date không phải là ngoại lệ. Chỉ cần nhìn vào hệ thống con I/O hoặc quá trình chuyển đổi từ AWT sang Swing ...

Và vì lý do đó, "đôi khi chúng tôi nên nhấn nút đặt lại". (người đã nói điều đó, btw.?)

5

Bạn có thể thấy bài đăng sau đây thú vị. Nó khá nhiều giải thích làm thế nào lớp Lịch đã vào Java API ở nơi đầu tiên, và làm sáng tỏ một số nguồn gốc của lớp ngày tháng.

The Seven Habits of Highly Dysfunctional Design

Các vấn đề liên quan