Сегодня у меня возникла странная проблема: у меня был метод, в котором в качестве аргументов были взяты два объекта Date. Вызывающий метод передал ссылку на тот же объект, что и оба из них (рассматриваемый метод был EqualsBuilder.append). Первый параметр получил отлично, а второй - нет. Это был новый объект Date, который отличался от первого в том смысле, что все поля, за исключением года и дня года, были установлены в 0. Обратите внимание, что у меня не было никакого кода, который бы скопировал объект ... Это ошибка в JVM?Почему JVM создает копию объекта при передаче его методу?
Код был довольно напряженным, и я заметил только это, потому что мой юнит-тест потерпел неудачу при сравнении того, что должно было быть тем же самым объектом (я инициализировал его каким-то случайным длинным).
Edit:
- Я не верил, что сам ...
- я не предполагал ошибку в JVM, я потратил буквально 4 часа, глядя на этот код и отладку.
- Я посмотрел в отладчике, чтобы убедиться, что они являются одним и тем же объектом (также будет проверяться с помощью метода == в методе вызова в понедельник).
- Я использую 1.6.0_17 для Windows XP
- Я не могу опубликовать реальный код прямо сейчас, сделаем это в понедельник.
Edit 2:
- После перезапуска Eclipse, я не могу воспроизвести ошибку
- У меня есть 7 глаз свидетелей, которые могут свидетельствовать, что это случилось :)
- на этих свидетелей сказал что на предыдущем концерте они столкнулись с чем-то до такой степени и что они столкнулись с этой ошибкой (или странным поведением) раз в 3 года
- , следовательно, я полагаю, что мои шансы на репродуцирование г ситуация довольно тонкая (я действительно хотел, чтобы я взял скриншоты)
Edit 3:
Вот код для данного класса:
импорта java.util .Дата; 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();
}
}
- И тест блок, который не удалось: импорт java.util.Arrays; import java.util.Date; импорт 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 есть ошибка (хотя это часть программного обеспечения, а программное обеспечение без ошибок).
Прямо сейчас я проверил код с конструктором, который вызвал ошибки, в первую очередь, возможно, мне посчастливится столкнуться с этим снова. Спасибо за отзывы.
Опубликовать код будет бесконечно ясным, чем его описание. –
Я этому не верю. Я согласен с @Jonathan Feinberg. Давайте посмотрим на код. – bmargulies
I третий это. Посмотрим на код. –