FindBugs - как решить EQ_COMPARETO_USE_OBJECT_EQUALS - PullRequest
11 голосов
/ 09 апреля 2010

Я здесь невежественен ...

 1: private static class ForeignKeyConstraint implements Comparable<ForeignKeyConstraint> {
 2: String tableName;
 3: String fkFieldName;
 4: 
 5: public int compareTo(ForeignKeyConstraint o) {
 6:    if (this.tableName.compareTo(o.tableName) == 0) {
 7:            return this.fkFieldName.compareTo(o.fkFieldName);
 8:        }
 9:        return this.tableName.compareTo(o.tableName);
10:    }
11: }

В строке 6 я получаю от FindBugs: Bug: net.blabla.SqlFixer$ForeignKeyConstraint defines compareTo(SqlFixer$ForeignKeyConstraint) and uses Object.equals()

Ссылка на определение

Я не знаю, как это исправить.

Ответы [ 5 ]

15 голосов
/ 09 апреля 2010

Эта ошибка означает, что вы не переопределяете equals в ForeignKeyConstraint (и, следовательно, наследуете equals от Object), поэтому следующее неверно (из javadoc compareTo):

Настоятельно рекомендуется, но не обязательно, чтобы (x.compareTo(y)==0) == (x.equals(y)). Вообще говоря, любой класс, который реализует интерфейс Comparable и нарушает это условие, должен четко указывать на этот факт. Рекомендуемый язык: «Примечание: этот класс имеет естественный порядок, не совместимый с равным».

Чтобы исправить проверку FindBugs, переопределите equals - и hashCode - если это имеет смысл, что обычно имеет место (или исключите проверку для этого класса и документ, подтверждающий, что ваш класс нарушает это условие, используя предлагаемую заметку).

4 голосов
/ 09 апреля 2010

Это говорит вам о том, что есть вероятность, что CompareTo () и equals () могут не согласиться. И они должны, действительно, никогда не соглашаться.

Метод equals () наследуется от java.lang.Object, который по умолчанию проверяет, являются ли два объекта одинаковыми instance . Ваш метод compareTo сравнивает объекты на основе tableName и fkFieldName. Таким образом, вы потенциально окажетесь в ситуации, когда CompareTo заявляет, что два объекта совпадают (потому что tableName и fkFieldName совпадают), но равно состояниям, которые они различны (потому что это разные экземпляры).

Существует несколько API-интерфейсов Java, которые зависят от CompareTo и равнозначны; это часть языка Java и считается основным языковым контрактом. Идеально реализовать метод equals (и hashcode) для проверки на равенство на основе tableName и fkFieldName.

4 голосов
/ 09 апреля 2010

Вы можете решить эту проблему с помощью метода equals (). Обратитесь к определению FindBugs:

"Как правило, значение compareTo должно возвращать ноль в том и только в том случае, если equals возвращает true. Если это нарушается, в таких классах, как PriorityQueue, будут происходить странные и непредсказуемые ошибки."

"Настоятельно рекомендуется, но не обязательно, чтобы (x.compareTo (y) == 0) == (x.equals (y))."

Другим примером является TreeSet. Он реализует проверки на равенство, вызывая CompareTo, а реализация CompareTo, которая несовместима с equals, заставляет TreeSet нарушать контракт интерфейса Set, что может привести к сбою программы.

2 голосов
/ 09 апреля 2010

Вы пробовали также переопределить метод equals в SqlFixer.ForeignKeyConstraint?

Я полагаю, что основа предупреждения состоит в том, что, как указано в определении, могут происходить странные вещи, если вы переопределяете сравнение, а не равно.

Для получения дополнительной информации ознакомьтесь с Effective Java Джошуа Блоха, 2-е издание . Пункт 12 более подробно рассказывает о плюсах и минусах реализации Comparable и о некоторых вещах, на которые стоит обратить внимание.

0 голосов
/ 11 сентября 2011

Findbugs доволен:

public int compareTo(ForeignKeyConstraint o) {
    if (this.equals(o)) {
        return 0;
    } else if (this.tableName.equals(o.tableName)) {
        // fkFieldName must be different
        return this.fkFieldName.compareTo(o.fkFieldName);
    } else {
        // tableName must be different
        return this.tableName.compareTo(o.tableName);
    }
}

@Override
public equals() {
  ...
}

@Override
public int hashCode() {
  ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...