2009-12-04 27 views
0

我今天遇到了一個奇怪的問題:我有把兩個Date對象作爲參數的方法。調用方法通過引用與它們兩者相同的對象(所討論的方法是EqualsBuilder.append)。第一個參數通過很好,但第二個參數沒有。這是一個新的Date對象,這是從意義上的第一個,除了年月日之間的所有字段都設置爲0。注意,我沒有說會複製對象的任何代碼,不同的...是JVM中的錯誤?爲什麼將它傳遞給一個方法時,JVM創建對象的副本?

的代碼是相當簡單明瞭,我只注意到,因爲我的單元測試上的東西應該是非常相同的對象比較失敗(我用一些隨機的長初始化它)。

編輯

  • 我不相信自己...
  • 我沒有承擔JVM錯誤,我硬是花了4小時這段代碼盯着調試它。
  • 我看着在調試器來驗證它們是同一個對象(也將與調用方法==測試星期一)。
  • 我在Windows XP上使用1.6.0_17
  • 我無法在第二秒發佈實際代碼,星期一就會這樣做。

編輯2

  • 。重新啓動Eclipse之後,我無法重現錯誤
  • 我有7名目擊者可以證明,它發生了:)
  • 這些證人說這在以前的演出,他們在3年內
  • 因此遇到事情到那種程度,他們遇到了這個錯誤(或怪異的行爲)一次,我想,我的勝算reproducin的克形勢相當渺茫(我真希望我沒采取截圖)

編輯3

  • 下面是有問題的類代碼:

    進口的java.util 。日期; import java.util.List;

import org.apache.commons.lang.builder.EqualsBuilder; 進口org.apache.commons.lang.builder.HashCodeBuilder;

公共類Foo {

private final long roadId; 
private final Date creationDate; 
private final Date editDate; 
private final List<String> vehicleTypes; 
private final boolean continuous; 

public Foo(final long roadId, final Date creationDate, final Date editDate, final List<String> vehicleTypes, final boolean continuous) { 
    super(); 
    this.roadId = roadId; 
    this.creationDate = creationDate; 
    this.editDate = editDate; 
    this.vehicleTypes = vehicleTypes; 
    this.continuous = continuous; 
} 

public long getRoadId() { 
    return roadId; 
} 

public Date getCreationDate() { 
    return creationDate; 
} 

public Date getEditDate() { 
    return editDate; 
} 

public List<String> getVehicleTypes() { 
    return vehicleTypes; 
} 

public boolean isContinuous() { 
    return this.continuous; 
} 

@Override 
public int hashCode() { 
    final HashCodeBuilder builder = new HashCodeBuilder(); 
    builder.append(this.roadId); 
    builder.append(this.creationDate); 
    builder.append(this.editDate); 
    builder.append(this.vehicleTypes); 
    builder.append(this.continuous);   
    return builder.toHashCode(); 
} 

@Override 
public boolean equals(final Object obj) { 
    if (this == obj) { 
     return true; 
    } 
    if (!(obj instanceof Foo)) { 
     return false; 
    } 
    final Foo other = (Foo)obj; 
    EqualsBuilder builder = new EqualsBuilder(); 
    builder.append(this.roadId, other.roadId); 
    builder.append(this.creationDate, other.creationDate); 
    builder.append(this.editDate, other.editDate); 
    builder.append(this.vehicleTypes, other.vehicleTypes); 
    builder.append(this.continuous, other.continuous); 
    return builder.isEquals(); 
} 

}

  • 而失敗的單元測試: 進口java.util.Arrays中; import java.util.Date; import java.util。清單;

進口靜態org.junit.Assert *。 import org.junit.Before; import org.junit.Test;

公共類FooTest {

private static final boolean CONTINUOUS = true; 
private static final Date CREATION_DATE = new Date(12345678901L); 
private static final Date EDIT_DATE = new Date(987654321654321L); 
private static final long ROAD_ID = 101; 
private static final List<String> VEHICLE_TYPES = Arrays.<String> asList("TEST"); 
private Foo nonEmpty;  
private Foo otherNonEmpty; 

@Before 
public void setUp() { 
    this.nonEmpty = new Foo(FooTest.ROAD_ID, FooTest.CREATION_DATE, 
      FooTest.EDIT_DATE, FooTest.VEHICLE_TYPES, true); 
    this.otherNonEmpty = new Foo(FooTest.ROAD_ID, FooTest.CREATION_DATE, 
      FooTest.EDIT_DATE, FooTest.VEHICLE_TYPES, FooTest.CONTINUOUS); 

} 

@Test 
public void testEquals() { 
    assertTrue(this.nonEmpty.equals(this.otherNonEmpty)); 
} 

}

現在,如果我改變了這一點:

private static final Date CREATION_DATE = new Date(12345678901L); 
private static final Date EDIT_DATE = new Date(987654321654321L); 

這樣:

private static final Date CREATION_DATE = new Date(109,1,11); 
private static final Date EDIT_DATE = new Date(110,3,13); 

它工作得很好。

我不認爲該代碼是錯誤的,特別是在重新啓動之後,JVM所有測試通過。同時,我知道JVM中存在一個錯誤的可能性很小(儘管它是一個軟件,沒有軟件是沒有bug的)。

現在我在構造函數中的代碼,首先導致的錯誤檢查了,也許我將有幸再次遇到。感謝您的反饋。

+8

要發佈代碼將比嘗試描述它更加清晰。 – 2009-12-04 22:19:04

+6

我不相信。我同意@Jonathan Feinberg。讓我們看看代碼。 – bmargulies 2009-12-04 22:20:42

+1

我第三。讓我們看看一些代碼。 – 2009-12-04 22:32:44

回答

3

你的說法,當它作爲一個方法參數傳遞一個JVM被複制對象是非凡的,而且(我)令人難以置信沒有一些具體的證據。請提供您認爲會出現此行爲的調用/調用方法的源代碼以及JVM版本和硬件/操作系統平臺的詳細信息。

"Extraordinary claims require extraordinary proof"


。重新啓動Eclipse之後,我無法重現指向這是一個 「古怪的Eclipse」 問題的bug

。我期望Eclipse怪異意味着你正在運行的代碼與你正在查看的源代碼不匹配。但我們絕對不會知道......

0

此代碼:

public void testDates() { 
    Date d = new Date(); 

    runTest(d, d); 
} 

private void runTest(Date a, Date b) { 
    System.out.println(a +" " +b); 
} 

印刷這樣的結果對我來說:

Fri Dec 04 22:14:28 GMT 2009 Fri Dec 04 22:14:28 GMT 2009 

不適合您所描述的情況呢? (顯然結果沒有)。 EqualsBuilder的來源看起來並不像它有什麼不同之處。

+0

它可怕。當然結果不會:( – 2009-12-23 20:16:39

1

如果對象不同,它們首先不能相同。我的懷疑是你認爲你有兩個引用同一個對象,但你有兩個對象。你怎麼確定你只有一個對象?

2

在傳入方法時,Java對象從不被複制。在Java中,所有變量都是按值傳遞的,而在對象中,對象的引用是按值傳遞的。有從來沒有複製完成。

+0

永遠不會說永不......我不能相信這一點。 – 2009-12-23 20:16:06

+0

@Bartosz:在這種情況下,永遠不要說永遠是錯的。 – Fredrik 2009-12-23 20:24:32

1

我打算建議java.sql.Date在這種方式混在一起(根據聲明,「所有字段除了年月和日被設置爲0」)。

相關問題