2009-12-04 26 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”)。

相关问题