Договір щодо, що 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перевіряє, чи є якийсь інший об'єкт "рівним"thisnullпосилання не дає жодного іншого об'єкта для тесту- Тому
equals(null)слід кидатиNullPointerException