Не верьте кодогенераторам,

Рубрика: 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. По крайней мере, это честнее, чем создавать нерабочий код.

Учитывайте эти грабли, когда в следующий раз будете нажимать кнопочку кодогенератора.

Комментариев: 7

7 Responses to “Не верьте кодогенераторам,”

Комментарии:

  1. Сергей

    Супер. Пост нашел реальное применение через 3 минуты после прочтения.
    Спасибо.

  2. Владимир Долженко

    при всей моей любви к eclipse кодогенератор equals/hashCode у него ужасен до безобразия – проще и лучше написать руками

  3. Olexandr Kundirenko

    Никогда не любил статическую кодегенерацию, для меня это как симптом что нужно что-то зарефакторить
    А чем вас не устраивают org.apache.commons.lang.EqualsBuider && HashCodeBuilder?

  4. Smudgy

    Olexandr Kundirenko +1.
    Я использую апачевские билдеры еще и для того чтобы в иерархии ниже использовать вызов appendSuper(). Очень полезно для бинов статистики.

    По поводу eclipse built-in builders, их я использую для быстрого создания бина, если все поля простых типов. Это у меня занимает 1 минуту (спасибо Eclipse Hot Keys).

    Ну а по поводу качества, думаю как раз для простых типов (в код не смотрел)в апаче используется тот же самый метод что и в eclipse.

  5. Vladimir

    К сожалению кодогенирация 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;

  6. Smudgy

    Наверное все-таки в Эклипсе сделали эти методы для тех кто не углубляется в недра явы, для быстрого и удобочитаемого кода.

  7. corsair

    баг репорт написав?

Leave a Reply