我有一个非常简单的Pair类,定义如下:

public class Pair<L, R> {

    private L left;
    private R right;

    public Pair(L left, R right) {
        this.left = left;
        this.right = right;
    }

    public L getLeft() {
        return this.left;
    }

    public R getRight() {
        return this.right;
    }

    public String toString() {
        return String.format("(%s, %s)", left, right);
    }

    public int hashCode() {
        int hashFirst = left != null ? left.hashCode() : 0;
        int hashSecond = left != null ? right.hashCode() : 0;

        return (hashFirst + hashSecond) * hashSecond + hashFirst;
    }

    public Boolean equals(Pair other) {
        if (other == null) {
            return false;
        }

        return left.equals(other.getLeft()) && right.equals(other.getRight());
    }
}


然后,我将Position类定义如下:

public class Position {

    private Pair<Integer, Integer> pair;

    public Position(Integer x, Integer y) {
        this.pair = new Pair<Integer, Integer>(x, y);
    }

    public Integer getX() {
        return this.pair.getLeft();
    }

    public Integer getY() {
        return this.pair.getRight();
    }

    public boolean equals(Position other) {
        if (other == null) {
            return false;
        }

        boolean b = getX() == other.getX() && getY() == other.getY();
        System.out.println(String.format("%s.equals(%s): %s", this, other, b));
        return b;
    }

    public int hashCode() {
        return pair.hashCode();
    }

    public String toString() {
        return String.format("(%d, %d)", this.pair.getLeft(),
                              this.pair.getRight());
    }

}


很好但是,当我尝试进行测试时,会发生一些奇怪的事情。

public class PositionTests extends TestCase {

    private Position posOne;
    private Position posTwo;
    private Position posThree;

    public PositionTests() {
        posOne = new Position(7, 6);
        posTwo = new Position(12, 7);
        posThree = new Position(7, 6);
    }

    public void testCreationX() {
        assertEquals(posOne.getX(), (Integer) 7);
    }

    public void testCreationY() {
        assertEquals(posOne.getY(), (Integer) 6);
    }

    public void testEquality() {
        // System.out.println("p1.e(p3): " + posOne.equals(posThree));
        // System.out.println("p3.e(p1): " + posThree.equals(posOne));
        //assertEquals(posOne, posThree);
        assertEquals(posThree, posOne);
    }

    public void testInequality() {
        assertFalse(posOne.equals(posTwo));
    }

    public void testXEquality() {
        assertEquals(posOne.getX(), posThree.getX());
    }

    public void testYEquality() {
        assertEquals(posOne.getY(), posThree.getY());
    }

    public void testSymmTrue() {
        assertTrue(posOne.equals(posThree) == posThree.equals(posOne));
    }

    public void testSymmFalse() {
        assertTrue(posOne.equals(posTwo) == posThree.equals(posTwo));
    }

    public void testHashSetSame() {
        Set<Position> hSet = new HashSet<Position>();
        hSet.add(posOne);
        hSet.add(posThree);
        hSet.add(posTwo);
        hSet.add(posOne);
        hSet.add(posOne);
        hSet.add(posOne);
        assertTrue(hSet.size() == 3);
    }

    public void testListContainsSuccess() {
        List<Position> pList = new ArrayList<Position>();
        pList.add(posOne);
        pList.add(posTwo);
        assertTrue(pList.contains(posOne));
    }

    public void testListContainsSuccessDiff() {
        List<Position> pList = new ArrayList<Position>();
        pList.add(posOne);
        pList.add(posTwo);
        // System.out.println(pList);
        // System.out.println(posThree);
        Boolean b = pList.contains(posThree);
        System.out.println("contains: " + b);
        assertTrue(pList.contains(posThree));
    }

    public void testListContainsFail() {
        List<Position> pList = new ArrayList<Position>();
        pList.add(posOne);
        pList.add(posThree);
        assertFalse(pList.contains(posTwo));
    }

}


测试的相关输出如下:

    [junit] ------------- Standard Output ---------------
    [junit] JUnit version is: 3.8.2
    [junit] contains: false
    [junit] (7, 6).equals((7, 6)): true
    [junit] (7, 6).equals((7, 6)): true
    [junit] (7, 6).equals((12, 7)): false
    [junit] (7, 6).equals((12, 7)): false
    [junit] (7, 6).equals((12, 7)): false
    [junit] (7, 3).equals((7, 4)): false
    [junit] ------------- ---------------- ---------------
    [junit]
    [junit] Testcase: testListContainsSuccessDiff took 0.005 sec
    [junit]     FAILED
    [junit] null
    [junit] junit.framework.AssertionFailedError
    [junit]     at com.group7.dragonwars.tests.PositionTests.testListContainsSuccessDiff(PositionTests.java:92)
    [junit]
    [junit] Testcase: testListContainsFail took 0 sec
    [junit] Testcase: testYEquality took 0 sec
    [junit] Testcase: testSymmTrue took 0.014 sec
    [junit] Testcase: testSymmFalse took 0.001 sec
    [junit] Testcase: testHashSetSame took 0 sec
    [junit] Testcase: testListContainsSuccess took 0 sec
    [junit] Testcase: testCreationY took 0 sec
    [junit] Testcase: testEquality took 0.001 sec
    [junit]     FAILED
    [junit] expected:<(7, 6)> but was:<(7, 6)>
    [junit] junit.framework.AssertionFailedError: expected:<(7, 6)> but was:<(7, 6)>
    [junit]     at com.group7.dragonwars.tests.PositionTests.testEquality(PositionTests.java:43)
    [junit]
    [junit] Testcase: testInequality took 0.001 sec
    [junit] Testcase: testXEquality took 0 sec
    [junit] Testcase: testCreationX took 0 sec
    [junit] Test com.group7.dragonwars.tests.AllTests FAILED


现在已经发布了所有相关代码和测试结果,我的问题是为什么assertEquals(posOne,posThree)以及对contains()的调用会失败?如您在测试输出的顶部所见,.equals()返回true。我很困惑为什么这些失败了。在整个程序中,我不得不使用手动列表遍历和手动调用equals()来检查列表成员身份,但是为什么呢? List的文档说

Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e)).


但是,.contains()失败。什么...?

最佳答案

如果将@Override批注添加到equals()方法中,则会看到问题。参数类型必须为Object,而不是Position

@Override
public boolean equals(Object other) {


另外,Pair.hashCode()中有一个错字。

    int hashFirst = left != null ? left.hashCode() : 0;
    int hashSecond = left != null ? right.hashCode() : 0;
                     ^^^^^

关于java - 奇怪的assertEquals并包含行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15838197/

10-12 02:55