Какие варианты реализации equals для строки в Java возвращают false при несовпадении типов
Что проверяют
Знаете ли вы контракт equals и понимаете ли, что сравнение с объектом другого типа должно давать false, а не исключение. Через строку обычно выходят на общий вопрос: instanceof или getClass() в собственном equals, и что при этом происходит с симметрией.
Как отвечать
Начните с устройства String.equals(Object): сначала проверка ссылки this == anObject, затем instanceof String, и только потом сравнение содержимого. Значит, false вернётся в трёх случаях: другой тип (Integer, StringBuilder), null и строка с другим содержимым. Исключения не будет.
Варианты сравнения, которые стоит назвать:
a.equals(b):falseпри чужом типе и приnullв аргументе, но NPE, еслиnullоказался самa;"literal".equals(x): константа слева защищает от NPE;Objects.equals(a, b): безопасен кnullс обеих сторон, дваnullсчитаются равными;contentEquals(CharSequence): сравнивает строку сStringBuilderилиStringBufferпо содержимому, тип другой, а результат может бытьtrue;equalsIgnoreCase(String): принимает толькоString, поэтому чужой тип ловится ещё компилятором.
Для своих классов покажите два шаблона. С instanceof (удобно с pattern matching: if (!(o instanceof Point p)) return false;) допускаются подклассы, но если подкласс переопределит equals, нарушится симметрия. С getClass() != o.getClass() сравнение строгое. У String разницы нет, класс final. И напомните, что вместе с equals переопределяется hashCode, иначе объект потеряется в HashMap.
Где спотыкаются
Думают, что equals с объектом другого типа бросает ClassCastException. По контракту метод обязан вернуть false, а приведение типа без проверки как раз ошибка реализации.
Сравнивают строки через ==. Иногда это срабатывает из-за пула строк, поэтому ошибка всплывает только на строках, собранных в рантайме.
Ждут true от "abc".equals(new StringBuilder("abc")). Результат false, для такого сравнения нужен contentEquals или toString().