2013-04-05 76 views
1

我有一個非常簡單的Pair類定義如下:怪異的assertEquals,幷包含行爲

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()); 
    } 
} 

我再定義一個位置類,如下所示:

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)以及通話包含()失敗?正如您在測試輸出的頂部所看到的,.equals()返回true。我很困惑,爲什麼這些失敗。在整個我的程序中,我不得不使用手動列表遍歷並手動調用equals()來檢查列表成員資格,但是爲什麼?列表說明文件

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()失敗。什麼......?

回答

2

如果將一個@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; 
        ^^^^^ 
+0

哦哇,我一直在做錯了我的一生。非常感謝你。 是的,在hashCode真正的錯誤!謝謝! – 2013-04-05 16:00:31