Может ли что-нибудь предупредить меня против type.equals (incompatibleType)? - PullRequest
11 голосов
/ 26 октября 2011

Есть ли какой-нибудь инструмент, который может предостеречь меня от следующего вида кода:

if ( someClass.equals( someString ))

Например:

if ( myObject.getClass().equals( myClassName ))

Такая вещь является допустимой Java (равно принимает объект), но никогда не будет иметь значение true (класс никогда не будет равняться строке), так что это почти наверняка ошибка.

Я проверил Eclipse, FindBugs и PMD, но никто не поддерживает эту функцию?

Ответы [ 3 ]

8 голосов
/ 26 октября 2011

Да, IntelliJ IDEA имеет такую ​​проверку, которая, по моему мнению, включена по умолчанию. Это помечает следующее:

Class<?> clazz = String.class;
if (clazz.equals("foo")) {
   //...
}

С предупреждением:

'equals ()' между объектами необратимых типов.

Инспекция может быть включена / отключена через Настройки-> Настройки проекта-> Инспекции, затем в разделе Вероятные ошибки установите / снимите флажок "'equals ()" между объектами необратимых типов. "

FindBugs также должен перехватить это с помощью "EC: вызов equals () для сравнения разных типов" проверка ошибок. Он может быть интегрирован с Eclipse, как вы знаете.

Хотя это не серебряная пуля; они не могут читать ваши мысли. Лучшее, на что вы можете надеяться, это то, что оно будет способствовать ложным срабатываниям, а не ложным отрицаниям.

1 голос
/ 26 октября 2011

Это идея интерфейса IEquatable<T> в .NET: обеспечение механизма для типов для реализации того, что я назову строго типизированным равенством.Существует также интерфейс IEqualityComparer<T>, позволяющий реализовать эту логику в отдельном типе.

Согласно этот вопрос StackOverflow (ответил Джон Скит, который, как правило, знает, что онговоря о), в Java, похоже, нет никакого эквивалента.

Конечно, вы всегда можете реализовать такую ​​вещь самостоятельно для своих типов, но это не принесет вам пользы с типами, которыеявляются частью библиотек базовых классов Java.Для обнаружения таких проблем во время компиляции вам лучше всего использовать какой-либо инструмент анализа ( Марк Питерс указывает , очевидно, есть встроенный в IntelliJ IDEA), который может предложить вам , чтоопределенный код может быть подозрительным.В общем, если вы не тот, кто игнорирует предупреждения, этого должно быть достаточно.

1 голос
/ 26 октября 2011

То, что вы проверяете, не обязательно является «проблемой»: equals() объявляется в классе Object и принимает в качестве параметра Object.Классы переопределяют этот метод, и их реализация вполне может позволить объекту другого класса "равняться" целевому объекту.

Я сам делал это несколько раз, например, для разрешенияобъект, "равный" другому объекту, если другой объект (скажем, строка) соответствует ключевому полю цели:

class MyClass {
    private String id;

    public boolean equals(Object obj) {
        // Compare as if "this" is the id field
        return id.equals(obj instanceof MyClass ? ((MyClass)obj).id : obj);
    }

    public int hashCode() {
        return id.hashCode(); // so hashCode() agrees with equals()
    }
}

Это на самом деле довольно удобно, потому что следующий код будетработа по желанию:

List<MyClass> list = new ArrayList<MyClass>();
// collection methods will work with instances:
list.contains(someInstance);
list.remove(someInstance);
list.indexOf(someInstance);
// and with keys!
// handy if you can only get the key, for example from a web url parameter
list.contains("somekey");
list.remove("somekey");
list.indexOf("somekey");
...