Tôi thích câu hỏi này! Chủ yếu là vì nó hiếm khi được trả lời hoặc trả lời không tốt. Nó giống như chưa ai tìm ra nó. Lãnh thổ trinh nữ :)
Trước hết, thậm chí không nghĩ về việc sử dụng equals
. Hợp đồng equals
, như được định nghĩa trong javadoc, là một quan hệ tương đương (phản xạ, đối xứng và bắc cầu), không phải là một quan hệ bình đẳng. Vì vậy, nó cũng sẽ phải là đối xứng. Việc triển khai duy nhất của equals
điều đó là (hoặc từng có thể là) một quan hệ bình đẳng thực sự là quan hệ trong java.lang.Object
. Ngay cả khi bạn đã sử dụng equals
để so sánh mọi thứ trong biểu đồ, nguy cơ phá vỡ hợp đồng là khá cao. Như Josh Bloch đã chỉ ra trong Java hiệu quả , hợp đồng bằng rất dễ bị phá vỡ:
"Đơn giản là không có cách nào để mở rộng một lớp có thể khởi tạo và thêm một khía cạnh trong khi vẫn bảo toàn hợp đồng bằng"
Ngoài ra, phương pháp boolean có thực sự tốt không? Thật tuyệt khi thực sự gói gọn tất cả những điểm khác biệt giữa bản gốc và bản sao, bạn có nghĩ vậy không? Ngoài ra, ở đây tôi sẽ giả định rằng bạn không muốn phải bận tâm với việc viết / duy trì mã so sánh cho từng đối tượng trong biểu đồ, mà là bạn đang tìm kiếm thứ gì đó sẽ thay đổi tỷ lệ với nguồn khi nó thay đổi theo thời gian.
Soooo, những gì bạn thực sự muốn là một số loại công cụ so sánh trạng thái. Cách triển khai công cụ đó thực sự phụ thuộc vào bản chất của mô hình miền và các hạn chế về hiệu suất của bạn. Theo kinh nghiệm của tôi, không có viên đạn ma thuật chung chung. Và nó sẽ chậm qua một số lượng lớn các lần lặp lại. Nhưng để kiểm tra tính hoàn chỉnh của hoạt động sao chép, nó sẽ thực hiện công việc khá tốt. Hai lựa chọn tốt nhất của bạn là tuần tự hóa và phản chiếu.
Một số vấn đề bạn sẽ gặp phải:
- Thứ tự bộ sưu tập: Hai bộ sưu tập có nên được coi là giống nhau nếu chúng chứa các đối tượng giống nhau, nhưng theo thứ tự khác nhau không?
- Những trường nào cần bỏ qua: Tạm thời? Tĩnh không?
- Kiểu tương đương: Giá trị trường có nên cùng kiểu không? Hoặc là nó ok cho một trong những mở rộng khác?
- Còn nữa, nhưng tôi quên ...
XStream khá nhanh và kết hợp với XMLUnit sẽ thực hiện công việc chỉ trong vài dòng mã. XMLUnit rất hay vì nó có thể báo cáo tất cả sự khác biệt hoặc chỉ dừng lại ở điểm đầu tiên mà nó tìm thấy. Và đầu ra của nó bao gồm xpath tới các nút khác nhau, điều này thật tuyệt. Theo mặc định, nó không cho phép các bộ sưu tập không có thứ tự, nhưng nó có thể được cấu hình để làm như vậy. Việc tiêm một trình xử lý sự khác biệt đặc biệt (Được gọi là a DifferenceListener
) cho phép bạn chỉ định cách bạn muốn xử lý sự khác biệt, bao gồm cả việc bỏ qua thứ tự. Tuy nhiên, ngay khi bạn muốn làm bất cứ điều gì ngoài tùy chỉnh đơn giản nhất, thì việc viết sẽ trở nên khó khăn và các chi tiết có xu hướng bị ràng buộc vào một đối tượng miền cụ thể.
Sở thích cá nhân của tôi là sử dụng phản xạ để duyệt qua tất cả các trường đã khai báo và đi sâu vào từng trường, theo dõi sự khác biệt khi tôi tiếp tục. Lời cảnh báo: Không sử dụng đệ quy trừ khi bạn thích ngoại lệ tràn ngăn xếp. Giữ mọi thứ trong phạm vi với một ngăn xếp (sử dụngLinkedList
hoặc cái gì đó). Tôi thường bỏ qua các trường tạm thời và trường tĩnh, và tôi bỏ qua các cặp đối tượng mà tôi đã so sánh, vì vậy tôi không kết thúc trong các vòng lặp vô hạn nếu ai đó quyết định viết mã tự tham chiếu (Tuy nhiên, tôi luôn so sánh các trình bao bọc nguyên thủy bất kể điều gì , vì các ref của cùng một đối tượng thường được sử dụng lại). Bạn có thể định cấu hình mọi thứ từ trước để bỏ qua thứ tự bộ sưu tập và bỏ qua các loại hoặc trường đặc biệt, nhưng tôi muốn xác định chính sách so sánh trạng thái của mình trên chính các trường thông qua chú thích. Đây, IMHO, chính xác là ý nghĩa của các chú thích, để làm cho dữ liệu meta về lớp có sẵn trong thời gian chạy. Cái gì đó như:
@StatePolicy(unordered=true, ignore=false, exactTypesOnly=true)
private List<StringyThing> _mylist;
Tôi nghĩ rằng đây thực sự là một vấn đề thực sự khó, nhưng hoàn toàn có thể giải quyết được! Và một khi bạn có thứ gì đó phù hợp với mình, nó thực sự, thực sự, rất tiện dụng :)
Vậy thì chúc may mắn. Và nếu bạn nghĩ ra điều gì đó chỉ là thiên tài thuần túy, đừng quên chia sẻ!