我今天遇到了一个奇怪的问题:我有一个方法,它将两个Date对象作为参数。调用方法传递引用与它们两者完全相同的对象(所讨论的方法是EqualsBuilder.append)。第一个参数传递正常,但第二个参数没有。这是一个新的Date对象,与第一个不同,因为除了年月和日之外的所有字段都设置为0.请注意,我没有任何代码可以复制对象...是JVM中的一个错误?
代码非常简单,我只注意到,因为我的单元测试在比较应该是同一个对象时失败了(我用一些随机的长初始化它)。
编辑:
编辑2 :
编辑3 :
以下是相关课程的代码:
import java.util.Date; import java.util.List;
import org.apache.commons.lang.builder.EqualsBuilder; import 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();
}
}
import static 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中存在一个错误的可能性极小(尽管它是一个软件而且没有软件没有错误)。
现在我已经使用导致错误的构造函数检查了代码,或许我很幸运能够再次遇到错误。感谢您的反馈。
答案 0 :(得分:3)
当JVM作为方法参数传递时,JVM正在复制对象的断言是非常的,并且(对我而言)没有一些具体证据令人难以置信。请提供您认为具有此行为的调用/调用方法的源代码,以及JVM版本和硬件/ OS平台的详细信息。
"Extraordinary claims require extraordinary proof"
重新启动eclipse后,我无法重现错误
这表明这是一个“Eclipse古怪”问题。我希望Eclipse怪异意味着您运行的代码与您正在查看的源代码不匹配。但我们永远不会知道......
答案 1 :(得分:2)
在Java中,对象在传递给方法时永远不会被复制。在Java中,所有变量都按值传递,而在对象的情况下,对象的引用是按值传递的。 从不复制完成。
答案 2 :(得分:1)
如果对象不同,它们首先不能相同。我怀疑你认为你有两个对同一个对象的引用,但你有两个对象。你是怎么确定你只有一个物体的?
答案 3 :(得分:1)
我将建议java.sql.Date
以某种方式混淆(基于声明,“除了年月和日之外的所有字段都设置为0”)。
答案 4 :(得分: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的来源看起来并不像它有任何异常。