Договір щодо, що equals
стосується null
, такий:
Для будь-якого еталонного значення ненульового
x
,x.equals(null)
повинніreturn false
.
Це досить своєрідно, тому що якщо o1 != null
і o2 == null
, то маємо:
o1.equals(o2) // returns false
o2.equals(o1) // throws NullPointerException
Той факт, що o2.equals(o1) throws NullPointerException
це добре, бо він попереджає нас про помилку програміста. І все-таки, ця помилка не була б виявлена, якби з різних причин ми просто переключили її o1.equals(o2)
, яка замість цього просто "мовчки не вдалася б".
Тож питання такі:
- Чому це гарна ідея, яку
o1.equals(o2)
слідreturn false
замість кидатиNullPointerException
? - Чи буде поганою ідеєю, якщо там, де це можливо, ми перепишемо договір так, щоб замість нього
anyObject.equals(null)
завжди кидатиNullPointerException
?
У порівнянні з Comparable
На відміну від цього, в Comparable
контракті сказано:
Зверніть увагу, що
null
це не екземпляр будь-якого класу, іe.compareTo(null)
повинен кидатиNullPointerException
навіть, хочаe.equals(null)
повертаєтьсяfalse
.
Якщо NullPointerException
це підходить для compareTo
, чому це не для equals
?
Пов’язані запитання
Суто семантичний аргумент
Ось фактичні слова в Object.equals(Object obj)
документації:
Вказує, чи якийсь інший об'єкт "дорівнює" цьому.
А що таке предмет?
Об'єкти JLS 4.3.1
Об'єкт є екземпляром класу або масив.
Значення посилань (часто просто посилання ) є вказівниками на ці об'єкти та спеціальним
null
посиланням, яке посилається на жоден об'єкт .
Мій аргумент з цього боку справді простий.
equals
перевіряє, чи є якийсь інший об'єкт "рівним"this
null
посилання не дає жодного іншого об'єкта для тесту- Тому
equals(null)
слід кидатиNullPointerException