Не верьте кодогенераторам,
Рубрика: Java | 5 January 2009, 11:57 | juriy
или история одного маленького и противного бага.
Сегодня убил некоторое время, отлавливая мерзкий баг. Баг был наглядно продемонстрирован юнит тестом, который, помимо всего прочего, проверял два объекта на эквивалентность. Сами объекты – простые java-бины с парой полей – одно типа int, второе типа String[][]. Код для equals и hashCode поручил сгенерировать eclipse’у. Подвох оказался в том, что метод equals попросту не работал – он всегда возвращал false. При детальном рассмотрении проблема нашлась:
if (!Arrays.equals(fieldTwo, other.fieldTwo))
return false;
Все ведь просто, Arrays.equals сравнивает типы массива и количество элементов в каждом из них. Затем проверяет эквивалентность поэлементно. Первые две проверки проходят, а вот третья проваливается с треском. Ведь никакие два объекта-массива в java не эквиваленты:
System.out.println(new int[]{1}.equals(new int[]{1})) // Выведет false.
Для проверки эквивалентности многомерных массивов нужно использовать метод deepEquals, который, кстати, находится в том же классе Arrays.
Ради интереса я попробовал сгенерировать код equals и hashCode в IntelliJ IDEA. Idea отказалась учитывать многомерный массив при создании кода equals. По крайней мере, это честнее, чем создавать нерабочий код.
Учитывайте эти грабли, когда в следующий раз будете нажимать кнопочку кодогенератора.
Tweet
Супер. Пост нашел реальное применение через 3 минуты после прочтения.
Спасибо.
при всей моей любви к eclipse кодогенератор equals/hashCode у него ужасен до безобразия – проще и лучше написать руками
Никогда не любил статическую кодегенерацию, для меня это как симптом что нужно что-то зарефакторить
А чем вас не устраивают org.apache.commons.lang.EqualsBuider && HashCodeBuilder?
Olexandr Kundirenko +1.
Я использую апачевские билдеры еще и для того чтобы в иерархии ниже использовать вызов appendSuper(). Очень полезно для бинов статистики.
По поводу eclipse built-in builders, их я использую для быстрого создания бина, если все поля простых типов. Это у меня занимает 1 минуту (спасибо Eclipse Hot Keys).
Ну а по поводу качества, думаю как раз для простых типов (в код не смотрел)в апаче используется тот же самый метод что и в eclipse.
К сожалению кодогенирация eclipse оставлят желать лучшего :(. Всегда надо полагатся на свои глаза и конечно же юнит тесты. Особенно раздражает null check идиома в методе equals:
в еклипсе:
в idea:
if (url != null ? !url.equals(product.url) : product.url != null) return false;
в еклипсе:
if (url == null) {
if (other.url != null)
return false;
} else if (!url.equals(other.url))
return false;
Наверное все-таки в Эклипсе сделали эти методы для тех кто не углубляется в недра явы, для быстрого и удобочитаемого кода.
баг репорт написав?