Làm cách nào để khẳng định sự bình đẳng trên hai lớp mà không có phương thức bằng?


111

Giả sử tôi có một lớp không có phương thức equals (), mà không có nguồn. Tôi muốn khẳng định sự bình đẳng trên hai trường hợp của lớp đó.

Tôi có thể thực hiện nhiều xác nhận:

assertEquals(obj1.getFieldA(), obj2.getFieldA());
assertEquals(obj1.getFieldB(), obj2.getFieldB());
assertEquals(obj1.getFieldC(), obj2.getFieldC());
...

Tôi không thích giải pháp này vì tôi không có được bức tranh bình đẳng đầy đủ nếu một khẳng định sớm không thành công.

Tôi có thể tự mình so sánh thủ công và theo dõi kết quả:

String errorStr = "";
if(!obj1.getFieldA().equals(obj2.getFieldA())) {
    errorStr += "expected: " + obj1.getFieldA() + ", actual: " + obj2.getFieldA() + "\n";
}
if(!obj1.getFieldB().equals(obj2.getFieldB())) {
    errorStr += "expected: " + obj1.getFieldB() + ", actual: " + obj2.getFieldB() + "\n";
}
...
assertEquals("", errorStr);

Điều này mang lại cho tôi bức tranh bình đẳng đầy đủ, nhưng thật khó hiểu (và tôi thậm chí chưa tính đến các vấn đề rỗng có thể xảy ra). Tùy chọn thứ ba là sử dụng Bộ so sánh, nhưng so sánhTo () sẽ không cho tôi biết trường nào không bình đẳng.

Có cách nào tốt hơn để lấy những gì tôi muốn từ đối tượng mà không cần phân lớp con và ghi đè bằng (ugh) không?


Bạn đang tìm kiếm một thư viện so sánh sâu cho bạn? như deep-equals được đề xuất tại stackoverflow.com/questions/1449001/… ?
Vikdor

3
Tại sao bạn cần biết tại sao hai trường hợp không bằng nhau. Thông thường, việc triển khai equalphương thức chỉ cho biết liệu hai trường hợp có bằng nhau hay không và chúng tôi không quan tâm tại sao các nội dung lại không bằng nhau.
Bhesh Gurung

3
Tôi muốn biết những thuộc tính nào là không bằng nhau để tôi có thể sửa chữa chúng. :)
Ryan Nelson

Tất cả các Objects đều có một equalsphương thức, có thể bạn muốn nói rằng không có phương thức nào bị ghi đè.
Steve Kuo

Cách tốt nhất mà tôi có thể nghĩ đến là sử dụng một lớp wrapper hoặc một lớp con và sau đó sử dụng nó sau khi trọng các phương pháp tương đương ..
Thihara

Câu trả lời:


66

Mockito cung cấp một trình đối sánh phản chiếu:

Để sử dụng phiên bản Mockito mới nhất:

Assert.assertTrue(new ReflectionEquals(expected, excludeFields).matches(actual));

Đối với các phiên bản cũ hơn, hãy sử dụng:

Assert.assertThat(actual, new ReflectionEquals(expected, excludeFields));

17
Lớp này nằm trong gói org.mockito.internal.matchers.apachecommons. Mockito docs trạng thái: org.mockito.internal-> "Các lớp nội bộ, không được sử dụng bởi khách hàng." Bạn sẽ đặt dự án của mình vào rủi ro khi sử dụng điều này. Điều này có thể thay đổi trong bất kỳ phiên bản Mockito nào. Đọc ở đây: site.mockito.org/mockito/docs/current/overview-summary.html
luboskrnac

6
Sử dụng Mockito.refEq()thay thế.
Jeremy Kao

1
Mockito.refEq()không thành công khi các đối tượng không có id đặt = (
cavpollo

1
@PiotrAleksanderChmielowski, xin lỗi, khi làm việc với Spring + JPA + Entities, đối tượng Entity có thể có id (đại diện cho trường id của bảng cơ sở dữ liệu), vì vậy khi nó trống (một đối tượng mới chưa được lưu trữ trên DB), refEqkhông thành công để so sánh vì phương thức mã băm không thể so sánh các đối tượng.
cavpollo

3
Nó hoạt động tốt, nhưng dự kiến ​​và thực tế không đúng thứ tự. Nó phải là một cách khác xung quanh.
pkawiak

48

Có nhiều câu trả lời đúng ở đây, nhưng tôi cũng muốn thêm phiên bản của mình. Điều này dựa trên Assertj.

import static org.assertj.core.api.Assertions.assertThat;

public class TestClass {

    public void test() {
        // do the actual test
        assertThat(actualObject)
            .isEqualToComparingFieldByFieldRecursively(expectedObject);
    }
}

CẬP NHẬT: Trong khẳng định v3.13.2, phương pháp này không được chấp nhận như Woodz đã chỉ ra trong nhận xét. Khuyến nghị hiện tại là

public class TestClass {

    public void test() {
        // do the actual test
        assertThat(actualObject)
            .usingRecursiveComparison()
            .isEqualTo(expectedObject);
    }

}

3
Trong khẳng định v3.13.2, phương pháp này không được dùng nữa và khuyến nghị bây giờ là sử dụng usingRecursiveComparison()với isEqualTo(), sao cho dòng làassertThat(actualObject).usingRecursiveComparison().isEqualTo(expectedObject);
Woodz

45

Tôi thường triển khai usecase này bằng org.apache.commons.lang3.builder.EqualsBuilder

Assert.assertTrue(EqualsBuilder.reflectionEquals(expected,actual));

1
Gradle: androidTestCompile 'org.apache.commons: commons-lang3: 3.5'
Roel

1
Bạn cần phải thêm video này vào tập tin gradle của bạn dưới "phụ thuộc" khi bạn muốn sử dụng "org.apache.commons.lang3.builder.EqualsBuilder"
Roel

3
Điều này không cung cấp bất kỳ gợi ý nào về những trường chính xác không thực sự khớp.
Vadzim

1
@Vadzim Tôi đã sử dụng mã dưới đây để lấy Assert.assertEquals (ReflectionToStringBuilder.toString (dự kiến), ReflectionToStringBuilder.toString (thực tế));
Abhijeet Kushe

2
Phương pháp này yêu cầu tất cả các nút trong biểu đồ triển khai "bằng nhau" và "mã băm", về cơ bản làm cho phương pháp này gần như vô dụng. AssertJ's isEqualToComparingFieldByFieldRecursently là một trong những hoạt động hoàn hảo trong trường hợp của tôi.
John Zhang

12

Tôi biết nó hơi cũ, nhưng tôi hy vọng nó sẽ hữu ích.

Tôi gặp phải vấn đề tương tự như bạn, vì vậy, sau khi điều tra, tôi tìm thấy ít câu hỏi tương tự hơn câu hỏi này, và sau khi tìm ra giải pháp, tôi trả lời cùng một vấn đề, vì tôi nghĩ nó có thể giúp được người khác.

Câu trả lời được bình chọn nhiều nhất (không phải do tác giả chọn) của câu hỏi tương tự này , là giải pháp phù hợp nhất cho bạn.

Về cơ bản, nó bao gồm việc sử dụng thư viện có tên Unitils .

Đây là việc sử dụng:

User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertReflectionEquals(user1, user2);

Điều này sẽ vượt qua ngay cả khi lớp Userkhông triển khai equals(). Bạn có thể xem thêm các ví dụ và một khẳng định thực sự thú vị được gọi assertLenientEqualstrong hướng dẫn của họ .


1
Rất tiếc, Unitilsdường như đã chết, hãy xem stackoverflow.com/questions/34658067/is-unitils-project-alive .
Ken Williams

8

Bạn có thể sử dụng Apache commons lang ReflectionToStringBuilder

Bạn có thể chỉ định từng thuộc tính bạn muốn kiểm tra hoặc tốt hơn, loại trừ những thuộc tính bạn không muốn:

String s = new ReflectionToStringBuilder(o, ToStringStyle.SHORT_PREFIX_STYLE)
                .setExcludeFieldNames(new String[] { "foo", "bar" }).toString()

Sau đó, bạn so sánh hai chuỗi như bình thường. Đối với vấn đề phản xạ chậm, tôi cho rằng điều này chỉ để thử nghiệm, vì vậy không nên quá quan trọng.


1
Lợi ích bổ sung của phương pháp này là bạn nhận được đầu ra trực quan hiển thị các giá trị thực tế và mong đợi dưới dạng các chuỗi loại trừ các trường mà bạn không quan tâm.
fquinner

7

Nếu bạn đang sử dụng hamcrest cho các xác nhận của mình (khẳng địnhThat) và không muốn lấy thêm các lib kiểm tra, thì bạn có thể sử dụng SamePropertyValuesAs.samePropertyValuesAsđể xác nhận các mục không có phương thức bằng bị ghi đè.

Ưu điểm là bạn không phải kéo thêm một khung thử nghiệm khác và nó sẽ đưa ra một lỗi hữu ích khi xác nhận không thành công ( expected: field=<value> but was field=<something else>) thay vì expected: true but was falsenếu bạn sử dụng một cái gì đó như thế EqualsBuilder.reflectionEquals().

Nhược điểm là nó là một so sánh nông và không có tùy chọn để loại trừ các trường (giống như trong EqualsBuilder), vì vậy bạn sẽ phải làm việc xung quanh các đối tượng lồng nhau (ví dụ: loại bỏ chúng và so sánh chúng độc lập).

Trường hợp tốt nhất:

import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs;
...
assertThat(actual, is(samePropertyValuesAs(expected)));

Trường hợp xấu xí:

import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs;
...
SomeClass expected = buildExpected(); 
SomeClass actual = sut.doSomething();

assertThat(actual.getSubObject(), is(samePropertyValuesAs(expected.getSubObject())));    
expected.setSubObject(null);
actual.setSubObject(null);

assertThat(actual, is(samePropertyValuesAs(expected)));

Vì vậy, hãy chọn thuốc độc của bạn. Khuôn khổ bổ sung (ví dụ Unitils), lỗi không hữu ích (ví dụ: EqualsBuilder) hoặc so sánh nông (hamcrest).


1
Đối với công việc SamePropertyValuesA bạn phải thêm vào dự án dependecy hamcrest.org/JavaHamcrest/…
bigspawn

Tôi như giải pháp này, vì nó không thêm một "phụ thuộc thêm hoàn toàn * khác nhau!
GhostCat


2

Một số phương pháp so sánh phản ánh là nông

Một tùy chọn khác là chuyển đổi đối tượng thành json và so sánh các chuỗi.

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;    
public static String getJsonString(Object obj) {
 try {
    ObjectMapper objectMapper = new ObjectMapper();
    return bjectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
     } catch (JsonProcessingException e) {
        LOGGER.error("Error parsing log entry", e);
        return null;
    }
}
...
assertEquals(getJsonString(MyexpectedObject), getJsonString(MyActualObject))


1

So sánh từng trường:

assertNotNull("Object 1 is null", obj1);
assertNotNull("Object 2 is null", obj2);
assertEquals("Field A differs", obj1.getFieldA(), obj2.getFieldA());
assertEquals("Field B differs", obj1.getFieldB(), obj2.getFieldB());
...
assertEquals("Objects are not equal.", obj1, obj2);

1
Đây là điều tôi không muốn làm, vì một thất bại được khẳng định sớm sẽ che giấu những thất bại có thể xảy ra bên dưới.
Ryan Nelson

2
Xin lỗi, tôi đã bỏ sót phần đó trong bài đăng của bạn ... Tại sao "bức tranh bình đẳng đầy đủ" lại quan trọng trong môi trường unit-test? Tất cả các trường đều bằng nhau (bài kiểm tra đạt) hoặc chúng không bằng nhau (bài kiểm tra không thành công).
EthanB

Tôi không muốn phải chạy lại bài kiểm tra để phát hiện ra nếu các trường khác không bằng nhau. Tôi muốn biết trước tất cả các trường không bằng nhau để có thể giải quyết chúng ngay lập tức.
Ryan Nelson

1
Việc xác nhận nhiều trường trong một bài kiểm tra sẽ không được coi là một bài kiểm tra 'đơn vị' thực sự. Với phát triển theo hướng thử nghiệm truyền thống (TDD), bạn viết một thử nghiệm nhỏ và sau đó chỉ đủ mã để làm cho nó vượt qua. Có một xác nhận cho mỗi trường là cách chính xác để làm điều đó, chỉ cần không đặt tất cả các xác nhận vào một thử nghiệm. Tạo một thử nghiệm khác nhau cho từng xác nhận trường mà bạn quan tâm. Điều này sẽ cho phép bạn xem tất cả các lỗi với tất cả các trường chỉ với một lần chạy bộ. Nếu điều này khó, có thể mã của bạn không đủ mô-đun ngay từ đầu và có thể được cấu trúc lại thành một giải pháp sạch hơn.
Jesse Webb

Đây chắc chắn là một gợi ý hợp lệ và là cách thông thường để giải quyết nhiều xác nhận trong một thử nghiệm. Thách thức duy nhất ở đây là, tôi muốn có một cái nhìn tổng thể về đối tượng. Đó là, tôi muốn kiểm tra tất cả các trường đồng thời để xác minh rằng đối tượng ở trạng thái hợp lệ. Điều này không khó thực hiện khi bạn có một phương thức equals () bị ghi đè (tất nhiên là tôi không có trong ví dụ này).
Ryan Nelson

1

Các xác nhận AssertJ có thể được sử dụng để so sánh các giá trị mà không có #equalsphương thức được ghi đè đúng cách, ví dụ:

import static org.assertj.core.api.Assertions.assertThat; 

// ...

assertThat(actual)
    .usingRecursiveComparison()
    .isEqualTo(expected);

1

Vì câu hỏi này đã cũ, tôi sẽ đề xuất một cách tiếp cận hiện đại khác bằng cách sử dụng JUnit 5.

Tôi không thích giải pháp này vì tôi không có được bức tranh bình đẳng đầy đủ nếu một khẳng định sớm không thành công.

Với JUnit 5, có một phương thức được gọi là phương thức Assertions.assertAll()này sẽ cho phép bạn nhóm tất cả các xác nhận trong thử nghiệm của bạn lại với nhau và nó sẽ thực thi từng xác nhận và xuất ra mọi xác nhận không thành công ở cuối. Điều này có nghĩa là bất kỳ xác nhận nào không thành công trước sẽ không dừng việc thực hiện các xác nhận sau.

assertAll("Test obj1 with obj2 equality",
    () -> assertEquals(obj1.getFieldA(), obj2.getFieldA()),
    () -> assertEquals(obj1.getFieldB(), obj2.getFieldB()),
    () -> assertEquals(obj1.getFieldC(), obj2.getFieldC()));

0

Bạn có thể sử dụng phản xạ để "tự động hóa" việc kiểm tra bình đẳng đầy đủ. bạn có thể triển khai mã "theo dõi" bình đẳng mà bạn đã viết cho một trường, sau đó sử dụng phản chiếu để chạy thử nghiệm đó trên tất cả các trường trong đối tượng.


0

Đây là một phương pháp so sánh chung, so sánh hai đối tượng của cùng một lớp cho các giá trị của các trường của nó (lưu ý rằng chúng có thể truy cập được bằng phương thức get)

public static <T> void compare(T a, T b) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    AssertionError error = null;
    Class A = a.getClass();
    Class B = a.getClass();
    for (Method mA : A.getDeclaredMethods()) {
        if (mA.getName().startsWith("get")) {
            Method mB = B.getMethod(mA.getName(),null );
            try {
                Assert.assertEquals("Not Matched = ",mA.invoke(a),mB.invoke(b));
            }catch (AssertionError e){
                if(error==null){
                    error = new AssertionError(e);
                }
                else {
                    error.addSuppressed(e);
                }
            }
        }
    }
    if(error!=null){
        throw error ;
    }
}

0

Tôi tình cờ gặp một trường hợp tương tự.

Tôi muốn so sánh trên một thử nghiệm mà một đối tượng có giá trị thuộc tính tương tự như nhau, nhưng phương pháp như is(), refEq(), vv sẽ không làm việc vì những lý do như đối tượng của tôi có giá trị null trong mình idthuộc tính.

Vì vậy, đây là giải pháp tôi đã tìm thấy (tốt, một đồng nghiệp đã tìm thấy):

import static org.apache.commons.lang.builder.CompareToBuilder.reflectionCompare;

assertThat(reflectionCompare(expectedObject, actualObject, new String[]{"fields","to","be","excluded"}), is(0));

Nếu giá trị nhận được từ reflectionCompare0, có nghĩa là chúng bằng nhau. Nếu là -1 hoặc 1, chúng khác nhau về một số thuộc tính.



0

Tôi đã có cùng một câu hỏi hóc búa khi đơn vị thử nghiệm một ứng dụng Android và giải pháp đơn giản nhất mà tôi nghĩ ra là sử dụng Gson để chuyển đổi các đối tượng giá trị thực tế và giá trị mong đợi của tôi thành jsonvà so sánh chúng dưới dạng chuỗi.

String actual = new Gson().toJson( myObj.getValues() );
String expected = new Gson().toJson( new MyValues(true,1) );

assertEquals(expected, actual);

Những lợi thế của việc này trên tay so sánh lĩnh vực-by-field là bạn so sánh tất cả các lĩnh vực của bạn, vì vậy ngay cả nếu bạn sau này thêm một lĩnh vực mới để lớp học của bạn nó sẽ được tự động kiểm tra, so với nếu bạn đang sử dụng một loạt các assertEquals()trên tất cả các trường, sau đó sẽ cần được cập nhật nếu bạn thêm nhiều trường vào lớp của mình.

jUnit cũng hiển thị các chuỗi cho bạn để bạn có thể trực tiếp thấy chúng khác nhau ở điểm nào. Tuy nhiên, không chắc mức độ tin cậy của việc đặt hàng theo lĩnh vực Gson, đó có thể là một vấn đề tiềm ẩn.


1
Thứ tự trường không được Gson đảm bảo. Bạn có thể muốn JsonParse các chuỗi và so sánh JsonElements là kết quả của phân tích
Ozma

0

Tôi đã thử tất cả các câu trả lời và không có gì thực sự hiệu quả với tôi.

Vì vậy, tôi đã tạo phương thức của riêng mình để so sánh các đối tượng java đơn giản mà không cần đi sâu vào các cấu trúc lồng nhau ...

Phương thức trả về giá trị rỗng nếu tất cả các trường đều khớp hoặc chuỗi chứa chi tiết không khớp.

Chỉ các thuộc tính có phương thức getter mới được so sánh.

Cách sử dụng

        assertNull(TestUtils.diff(obj1,obj2,ignore_field1, ignore_field2));

Đầu ra mẫu nếu có sự không khớp

Đầu ra hiển thị tên thuộc tính và giá trị tương ứng của các đối tượng được so sánh

alert_id(1:2), city(Moscow:London)

Mã (Java 8 trở lên):

 public static String diff(Object x1, Object x2, String ... ignored) throws Exception{
        final StringBuilder response = new StringBuilder();
        for (Method m:Arrays.stream(x1.getClass().getMethods()).filter(m->m.getName().startsWith("get")
        && m.getParameterCount()==0).collect(toList())){

            final String field = m.getName().substring(3).toLowerCase();
            if (Arrays.stream(ignored).map(x->x.toLowerCase()).noneMatch(ignoredField->ignoredField.equals(field))){
                Object v1 = m.invoke(x1);
                Object v2 = m.invoke(x2);
                if ( (v1!=null && !v1.equals(v2)) || (v2!=null && !v2.equals(v1))){
                    response.append(field).append("(").append(v1).append(":").append(v2).append(")").append(", ");
                }
            }
        }
        return response.length()==0?null:response.substring(0,response.length()-2);
    }

0

Để thay thế cho chỉ junit, bạn có thể đặt các trường thành null trước khẳng định bằng:

    actual.setCreatedDate(null); // excludes date assertion
    expected.setCreatedDate(null);

    assertEquals(expected, actual);

-1

Bạn có thể đặt mã so sánh mà bạn đã đăng vào một số phương thức tiện ích tĩnh không?

public static String findDifference(Type obj1, Type obj2) {
    String difference = "";
    if (obj1.getFieldA() == null && obj2.getFieldA() != null
            || !obj1.getFieldA().equals(obj2.getFieldA())) {
        difference += "Difference at field A:" + "obj1 - "
                + obj1.getFieldA() + ", obj2 - " + obj2.getFieldA();
    }
    if (obj1.getFieldB() == null && obj2.getFieldB() != null
            || !obj1.getFieldB().equals(obj2.getFieldB())) {
        difference += "Difference at field B:" + "obj1 - "
                + obj1.getFieldB() + ", obj2 - " + obj2.getFieldB();
        // (...)
    }
    return difference;
}

Bạn có thể sử dụng phương pháp này trong JUnit như thế này:

khẳng địnhEquals ("Các đối tượng không bằng nhau", "", findDifferences (obj1, obj));

điều này không phức tạp và cung cấp cho bạn thông tin đầy đủ về sự khác biệt, nếu chúng tồn tại (thông qua không chính xác ở dạng bình thường của khẳng định nhưng bạn nhận được tất cả thông tin nên nó sẽ tốt).


-1

Điều này sẽ không giúp ích cho OP, nhưng nó có thể giúp bất kỳ nhà phát triển C # nào kết thúc ở đây ...

Giống như Enrique đã đăng , bạn nên ghi đè phương thức bằng.

Có cách nào tốt hơn để lấy những gì tôi muốn từ đối tượng mà không cần phân lớp con và ghi đè bằng (ugh) không?

Đề xuất của tôi là không sử dụng một lớp con. Sử dụng một lớp một phần.

Định nghĩa một phần lớp (MSDN)

Vì vậy, lớp học của bạn sẽ giống như ...

public partial class TheClass
{
    public override bool Equals(Object obj)
    {
        // your implementation here
    }
}

Đối với Java, tôi sẽ đồng ý với đề xuất sử dụng phản chiếu. Chỉ cần nhớ rằng bạn nên tránh sử dụng phản chiếu bất cứ khi nào có thể. Nó chậm, khó gỡ lỗi và thậm chí khó bảo trì trong tương lai vì IDE có thể phá vỡ mã của bạn bằng cách thực hiện đổi tên trường hoặc tương tự như vậy. Hãy cẩn thận!


-1

Từ bình luận của bạn đến những câu trả lời khác, tôi không hiểu bạn muốn gì.

Chỉ vì mục đích thảo luận, hãy nói rằng lớp đã ghi đè phương thức bằng.

Vì vậy, UT của bạn sẽ trông giống như sau:

SomeType expected = // bla
SomeType actual = // bli

Assert.assertEquals(expected, actual). 

Và bạn đã hoàn thành. Hơn nữa, bạn không thể có được "bức tranh bình đẳng đầy đủ" nếu khẳng định không thành công.

Theo những gì tôi hiểu, bạn đang nói rằng ngay cả khi kiểu đã ghi đè bằng, bạn sẽ không quan tâm đến nó, vì bạn muốn có được "bức tranh bình đẳng đầy đủ". Vì vậy, không có ích gì khi mở rộng và ghi đè bằng cả.

Vì vậy, bạn phải có các tùy chọn: hoặc so sánh thuộc tính theo thuộc tính, sử dụng kiểm tra phản chiếu hoặc mã hóa cứng, tôi sẽ đề xuất cách sau. Hoặc: so sánh các biểu diễn có thể đọc được của con người về các đối tượng này.

Ví dụ: bạn có thể tạo một lớp trợ giúp tuần tự hóa kiểu bạn muốn so sánh với tài liệu XML và so sánh với XML kết quả! trong trường hợp này, bạn có thể thấy trực quan những gì chính xác bằng và những gì không.

Cách tiếp cận này sẽ cho bạn cơ hội xem toàn cảnh nhưng nó cũng tương đối rườm rà (và dễ bị lỗi một chút lúc đầu).


Có thể thuật ngữ "bức tranh bình đẳng đầy đủ" của tôi gây nhầm lẫn. Việc triển khai bằng () thực sự sẽ giải quyết được vấn đề. Tôi muốn biết tất cả các trường không bằng nhau (có liên quan đến bình đẳng) cùng một lúc, nếu phải chạy lại bài kiểm tra. Việc sắp xếp thứ tự đối tượng là một khả năng khác, nhưng tôi không nhất thiết phải cần một số tương đương sâu. Tôi muốn sử dụng các triển khai bằng () của các thuộc tính nếu có thể.
Ryan Nelson

Tuyệt quá! Bạn hoàn toàn có thể sử dụng các thuộc tính ngang bằng, như bạn đã nêu trong câu hỏi của mình. Có vẻ như đây là giải pháp đơn giản nhất trong trường hợp này nhưng như bạn đã lưu ý, mã có thể rất khó chịu.
Vitaliy

-3

Bạn có thể ghi đè phương thức bằng của lớp như:

@Override
public int hashCode() {
    int hash = 0;
    hash += (app != null ? app.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    HubRule other = (HubRule) object;

    if (this.app.equals(other.app)) {
        boolean operatorHubList = false;

        if (other.operator != null ? this.operator != null ? this.operator
                .equals(other.operator) : false : true) {
            operatorHubList = true;
        }

        if (operatorHubList) {
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

Vâng, nếu bạn muốn so sánh hai đối tượng từ một lớp, bạn phải triển khai theo một cách nào đó phương thức bằng và phương thức mã băm


3
nhưng OP nói rằng ông không muốn ghi đè lên bằng, ông muốn một cách tốt hơn
Ankur
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.