2012-03-09 39 views
12

Tôi đang cố xác thực tuần tự hóa và xóa tuần tự bằng cách so sánh đối tượng kết quả với đối tượng gốc. Các thói quen có thể tuần tự hóa các lớp tùy ý và sâu sắc và do đó tôi muốn một thói quen so sánh có thể được đưa ra trong trường hợp ban đầu và cuối cùng và đi qua từng loại giá trị và so sánh các giá trị và đi sâu vào các loại tham chiếu để so sánh các giá trị.So sánh phản xạ sâu tương đương với

Tôi đã thử Apache Commons Lang EqualsBuilder.reflectionEquals(inst1, inst2) nhưng điều này không xuất hiện để làm một so sánh rất sâu, nó chỉ đơn giản là so sánh các loại tài liệu tham khảo cho bình đẳng chứ không phải lặn sâu hơn vào họ:

Các mã sau minh họa vấn đề của tôi. Cuộc gọi đầu tiên tới số reflectionEquals trả về giá trị thực nhưng lệnh trả về thứ hai là false.

Có thói quen thư viện nào mà mọi người có thể giới thiệu không?

class dummy { 
    dummy2 nestedClass; 
} 

class dummy2 { 
    int intVal; 
} 

@Test 
public void testRefEqu() { 

    dummy inst1 = new dummy(); 
    inst1.nestedClass = new dummy2(); 
    inst1.nestedClass.intVal = 2; 
    dummy inst2 = new dummy(); 
    inst2.nestedClass = new dummy2(); 
    inst2.nestedClass.intVal = 2; 
    boolean isEqual = EqualsBuilder.reflectionEquals(inst1.nestedClass, inst2.nestedClass); 
    isEqual = EqualsBuilder.reflectionEquals(inst1, inst2); 
} 
+0

Nếu độ tương phản bằng chỉ so sánh các tham chiếu, thì nó có lỗi. Nó nên làm nhiều hơn thế. – DwB

+0

@ DBB Tôi nghi ngờ ý định của mã là cho phép bạn thực hiện một cách tương đối equals() trong một lớp cụ thể. Điều này là khác với những gì tôi muốn mà là để phản ánh trên hai trường hợp đối tượng. Trong bối cảnh này nó không phải là một lỗi mà là một sự thất vọng! –

+0

Tôi mất một nửa ngày, của hành vi không có giấy tờ yếu này của EqualsBuilder. Nếu trường của một đối tượng được truyền là một hàm nguyên thủy thì hàm gọi là object.equals(). Rất thất vọng và vô dụng. – AlexWien

Trả lời

12

Từ câu trả lời cho câu hỏi này https://stackoverflow.com/a/1449051/116509 và từ một số thử nghiệm sơ bộ, có vẻ như Unitils' ReflectionAssert.assertReflectionEquals làm những gì bạn đang mong đợi . (Chỉnh sửa: nhưng có thể bị hủy bỏ, vì vậy bạn có thể thử AssertJ https://joel-costigliola.github.io/assertj/assertj-core-features-highlight.html#field-by-field-recursive)

Tôi rất lo lắng bởi hành vi này của EqualsBuilder vì vậy cảm ơn câu hỏi. Có khá một vài câu trả lời trên trang web này giới thiệu nó - Tôi tự hỏi, nếu những người giới thiệu nó nhận ra nó thực hiện điều này?

+0

Tôi chia sẻ bất ngờ của bạn mặc dù công bằng với EqualsBuilder, và khi tôi nhận xét về câu hỏi, tôi nghĩ rằng đó là một vấn đề của sự hiểu lầm ý định của thói quen. Có lẽ đây là cái gì đó có thể được làm rõ hơn. –

+2

javadoc nên được sửa đổi IMHO để làm cho nó rõ ràng hơn. – artbristol

+0

Tôi đã thực hiện một số thử nghiệm ban đầu trên assertReflectionEquals và nó dường như làm việc. Cảm ơn rất nhiều –

0

Thực hiện phương thức equals() trên các lớp được đề cập. Các bằng của mỗi cuộc gọi sẽ so sánh sự bình đẳng của các lớp lồng nhau (hoặc, nếu bạn thích, sẽ so sánh sự bình đẳng của các thành viên dữ liệu). Một phương pháp equals bằng văn bản chính xác sẽ luôn dẫn đến một so sánh sâu sắc.

Trong ví dụ của bạn, dummy bình đẳng lớp sẽ là một cái gì đó như thế này:

public boolean equals(Object other) 
{ 
    if (other == this) return true; 
    if (other instanceOf dummy) 
    { 
     dummy dummyOther = (dummy)other; 
     if (nestedClass == dummyOther.nestedClass) 
     { 
      return true; 
     } 
     else if (nestedClass != null) 
     { 
      return nestedClass.equals(dummyOther); 
     } 
     else // nestedClass == null and dummyOther.nestedClass != null. 
     { 
      return false; 
     } 
    } 
    else 
    { 
     return false; 
    } 
} 
+2

Tôi hiểu đây là cách bình thường để đạt được điều này, và đối với hầu hết các tình huống là cách được khuyến nghị. Cơ chế tích hợp để tính toán bình đẳng là mạnh mẽ và có thể mở rộng để cho phép các lớp tùy chỉnh xác định ý nghĩa bình đẳng nào cho chúng. Thật không may các yêu cầu của tôi ngăn cản tôi có thể thực hiện equals() trên tất cả các lớp lồng nhau và do đó tôi hy vọng sẽ sử dụng sự phản chiếu. Cảm ơn –

+0

Vấn đề với cách tiếp cận này là nó không thể xử lý đồ thị đối tượng tuần hoàn. So sánh một đồ thị đối tượng tuần hoàn bằng cách sử dụng phương pháp này sẽ dẫn đến đệ quy vô hạn. – jhegedus

+0

Tôi đồng ý rằng đồ thị đối tượng tuần hoàn sẽ là một vấn đề. như họ đang có serialization và thất bại hơn (có lẽ chỉ là một triệu chứng của serialization). – DwB

3

Một phương pháp sẽ là so sánh các đối tượng sử dụng sự phản chiếu - nhưng điều này là khó khăn. Một chiến lược khác sẽ được so sánh mảng byte của các đối tượng serialized:

class dummy implements Serializable { 
    dummy2 nestedClass; 
} 

class dummy2 implements Serializable { 
    int intVal; 
} 

@Test 
public void testRefEqu() throws IOException { 

    dummy inst1 = new dummy(); 
    inst1.nestedClass = new dummy2(); 
    inst1.nestedClass.intVal = 2; 

    dummy inst2 = new dummy(); 
    inst2.nestedClass = new dummy2(); 
    inst2.nestedClass.intVal = 2; 

    boolean isEqual1 = EqualsBuilder.reflectionEquals(inst1.nestedClass, inst2.nestedClass); 
    boolean isEqual2 = EqualsBuilder.reflectionEquals(inst1, inst2); 

    System.out.println(isEqual1); 
    System.out. println(isEqual2); 

    ByteArrayOutputStream baos1 =new ByteArrayOutputStream(); 
    ObjectOutputStream oos1 = new ObjectOutputStream(baos1); 
    oos1.writeObject(inst1); 
    oos1.close(); 

    ByteArrayOutputStream baos2 =new ByteArrayOutputStream(); 
    ObjectOutputStream oos2 = new ObjectOutputStream(baos2); 
    oos2.writeObject(inst1); 
    oos2.close(); 

    byte[] arr1 = baos1.toByteArray(); 
    byte[] arr2 = baos2.toByteArray(); 

    boolean isEqual3 = Arrays.equals(arr1, arr2); 

    System.out.println(isEqual3); 

} 

Ứng dụng của bạn serializes và deserializes đối tượng nên cách tiếp cận này có vẻ là giải pháp nhanh nhất (về hoạt động CPU) cho vấn đề của bạn.

+0

Chúc mừng Johnny, tôi đã nghĩ về việc so sánh hình thức tuần tự hóa, đó là một cách tiếp cận gọn gàng làm việc xung quanh những thiếu sót của EqualsBuilder. Điều đó nói rằng nó sẽ không hoàn toàn xác nhận serialization và de-serialization vì nó không hoàn toàn xác nhận rằng hình thức unserialized ban đầu là giống như hình thức deserialized. Kính trọng –

+0

Xin chào Howard, bạn có thể đưa ra ví dụ khi tình huống như vậy có thể xảy ra không? Tôi đã chắc chắn rằng một đối tượng có chính xác một biểu mẫu được tuần tự hóa và biểu diễn byte. – whysoserious

+0

Xin chào Johnny, hãy nhớ rằng lý do cho việc này là kiểm tra mã lỗi của tôi. Nếu serializer của tôi không serialize một lĩnh vực cụ thể sau đó so sánh các phiên bản serialized sẽ không phát hiện một vấn đề. –

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