Я использую Eclipse для генерации .equals()
и .hashCode()
, и есть опция с надписью «Использовать instanceof» для сравнения типов ». По умолчанию этот параметр отключен и используется .getClass()
для сравнения типов. Есть ли какой - либо причине я предпочитаю .getClass()
более instanceof
?
Без использования instanceof
:
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Использование instanceof
:
if (obj == null)
return false;
if (!(obj instanceof MyClass))
return false;
Я обычно проверяю instanceof
опцию, а затем захожу и снимаю if (obj == null)
галочку " ". (Это избыточно, поскольку нулевые объекты всегда будут давать сбой instanceof
.) Есть ли причина, по которой это плохая идея?
java
eclipse
equals
instanceof
койка
источник
источник
x instanceof SomeClass
ложно, еслиx
естьnull
. Следовательно, второй синтаксис не нуждается в нулевой проверке.Ответы:
Если вы используете
instanceof
, делая вашуequals
реализациюfinal
сохранит контракт симметрии метода:x.equals(y) == y.equals(x)
. Если этоfinal
кажется ограничительным, внимательно изучите ваше представление об эквивалентности объектов, чтобы убедиться, что ваши основные реализации полностью поддерживают контракт, установленныйObject
классом.источник
final
кажется ограничительным» (для обоихequals
иhashCode
), тогда используйтеgetClass()
равенство вместоinstanceof
того, чтобы сохранить требованияequals
контракта по симметрии и транзитивности .Джош Блох одобряет ваш подход:
Смотрите также этот так ответ .
Эффективная глава 3 Java также покрывает это.
источник
getClass
не нарушает LSP, поскольку LSP просто относится к тому, что можно сделать с существующими экземплярами, а не к тому, какие типы экземпляров могут быть созданы. Возвращаемый классgetClass
является неизменным свойством экземпляра объекта. LSP не подразумевает, что должна быть возможность создать подкласс, где это свойство указывает любой класс, кроме того, который его создал.Анжелика Лангерс Секреты равных вступает в это с долгим и подробным обсуждением нескольких распространенных и известных примеров, в том числе Джошом Блохом и Барбарой Лисков, обнаруживших пару проблем в большинстве из них. Она также попадает в
instanceof
противgetClass
. Некоторая цитата из этогоисточник
Основанием для использования
getClass
является обеспечение симметричного свойстваequals
договора. Из равных JavaDocs:Используя instanceof, можно не быть симметричным. Рассмотрим пример: собака расширяет животное. Животное
equals
делаетinstanceof
проверку животных. Собакиequals
делаетinstanceof
проверку собаки. Дайте Animal a и Dog d (с другими полями то же самое):Это нарушает симметричное свойство.
Чтобы строго следовать контракту равных, симметрия должна быть обеспечена, и, таким образом, класс должен быть одинаковым.
источник
a.equals(c)
иb.equals(c)
, тоa.equals(b)
(наивный подход созданияDog.equals
толькоreturn super.equals(object)
тогда, когда!(object instanceof Dog)
проверка дополнительных полей, когда это экземпляр Dog, не нарушил бы симметрию, но нарушил бы транзитивность)getClass()
проверку на равенство, или вы можете использоватьinstanceof
проверку, если делаете вашиequals
иhashCode
методыfinal
.Это что-то вроде религиозной дискуссии. Оба подхода имеют свои проблемы.
У Bloch есть еще один важный совет в Effective Java Second Edition :
источник
getClass
не нарушит LSP, если только базовый класс не задокументирует специально средство, с помощью которого можно сделать экземпляры разных подклассов одинаковыми. Какое нарушение LSP вы видите?getClass()
его не следует считать значимым, за исключением того факта, что рассматриваемый класс может быть преобразован в базовый класс, возврат изgetClass()
следует рассматривать как любое другое свойство, которое должно совпадать, чтобы экземпляры были равными.Поправьте меня, если я ошибаюсь, но getClass () будет полезен, если вы хотите убедиться, что ваш экземпляр НЕ является подклассом класса, с которым вы сравниваете. Если вы используете instanceof в этой ситуации, вы НЕ можете знать это, потому что:
источник
Если вы хотите убедиться, что только этот класс будет соответствовать, используйте
getClass() ==
. Если вы хотите соответствовать подклассам, тоinstanceof
это необходимо.Кроме того, instanceof не будет совпадать с нулем, но безопасно сравнивать с нулем. Так что вам не нужно проверять это на ноль.
источник
Это зависит от того, считаете ли вы, что подкласс данного класса равен его родителю.
здесь я бы использовал instanceof, потому что я хочу, чтобы LastName сравнивалось с FamilyName
здесь я бы использовал 'getClass', потому что класс уже говорит, что два экземпляра не эквивалентны.
источник
instanceof работает для инстинктов того же класса или его подклассов
ArryaList и RoleList являются экземплярами List
Пока
getClass () == o.getClass () будет истинным, только если оба объекта (this и o) принадлежат к одному и тому же классу.
Таким образом, в зависимости от того, что вам нужно сравнить, вы можете использовать один или другой.
Если ваша логика такова: «Один объект равен другим, только если они оба относятся к одному и тому же классу», вы должны выбрать «равно», что, как я думаю, в большинстве случаев.
источник
Оба метода имеют свои проблемы.
Если подкласс меняет идентичность, то вам нужно сравнить их фактические классы. В противном случае вы нарушаете симметричное свойство. Например, разные типы
Person
s не должны считаться эквивалентными, даже если они имеют одинаковые имена.Однако некоторые подклассы не меняют идентичность, и их нужно использовать
instanceof
. Например, если у нас есть куча неизменныхShape
объектов, тогда aRectangle
с длиной и шириной 1 должен быть равен единицеSquare
.На практике, я думаю, что первый случай, скорее всего, будет правдой. Как правило, создание подклассов является фундаментальной частью вашей личности, и быть точно таким же, как ваш родитель, за исключением того, что вы можете сделать одну маленькую вещь, не делает вас равными.
источник
На самом деле экземпляр проверки того, принадлежит ли объект какой-либо иерархии или нет. пример: объект Car относится к классу Vehical. Таким образом, «new Car () instance of Vehical» возвращает true. И "new Car (). GetClass (). Equals (Vehical.class)" возвращает false, хотя объект Car принадлежит классу Vehical, но он классифицируется как отдельный тип.
источник