【发布时间】:2009-12-04 22:10:49
【问题描述】:
我今天遇到了一个奇怪的问题:我有一个将两个 Date 对象作为参数的方法。调用方法传递了对与它们完全相同的对象的引用(有问题的方法是 EqualsBuilder.append)。第一个参数很好地传递了,但第二个参数没有。这是一个新的 Date 对象,它不同于第一个对象,因为除年月日以外的所有字段都设置为 0。请注意,我没有任何代码可以复制该对象... JVM 中的错误?
代码非常简单,我只注意到这是因为我的单元测试在比较应该是同一个对象时失败了(我用一些随机长初始化它)。
编辑:
- 我自己都不相信……
- 我没有假设 JVM 中存在错误,我花了 4 个小时盯着这段代码并对其进行调试。
- 我查看了调试器以确认它们是同一个对象(还将在星期一的调用方法中使用 == 进行测试)。
- 我在 Windows XP 上使用 1.6.0_17
- 我现在无法立即发布实际代码,将在星期一发布。
编辑 2:
- 重启eclipse后无法重现该bug
- 我有 7 位目击者可以证明它发生了 :)
- 其中一位目击者表示,在之前的演出中,他们遇到了这种程度的问题,并且他们每 3 年遇到一次此错误(或奇怪的行为)
- 因此,我想我重现这种情况的可能性很小(我真希望我已经截屏了)
编辑 3:
-
这是相关类的代码:
导入 java.util.Date; 导入 java.util.List;
导入 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; 导入 java.util.Date; 导入 java.util.List;
导入静态 org.junit.Assert.*; 导入 org.junit.Before; 导入 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中不太可能存在错误(尽管它是一个软件并且没有软件是没有错误的)。
现在我已经用最初导致错误的构造函数检查了代码,也许我有幸再次遇到这种情况。感谢您的反馈。
【问题讨论】:
-
发布代码比试图描述它要清晰得多。
-
我不相信。我同意@Jonathan Feinberg 的观点。让我们看看代码。
-
第三个。让我们看一些代码。
-
您永远不应该首先想到“VM 中的错误”。要么您的代码错误,要么您对应该发生的事情的直觉与现实不符。
-
更正:您有 7 位目击者说发生了一些事情。您和他们的问题是您(很可能)误解了实际发生的事情。如果没有具体、详细和可重复的证据(屏幕截图不足),就不可能说出真正发生的事情。非凡的陈述需要非凡的证据。