Я использую Java 21.
Я пытаюсь написать метод равенства для MyClass<T>, который определяет вложенный класс MyNested<T> extends Comparable и метод getNested(), который возвращает экземпляр класса MyNested<T>, который определен во время построения, и экземпляр MyClass<T>.
Мне неясно, как это сделать правильно.
Если я сделаю:
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if ((obj == null) || (this.getClass() != obj.getClass())) return false;
MyClass<?> other = (MyClass<?>) obj;
return this.getNested().compareTo(other.getNested()) == 0;
}
Я получаю ошибку компиляции:
java: incompatible types: MyClass.MyNested<capture#1 of ?> cannot be converted to MyClass.MyNested<T>
Это происходит потому, что методу MyNested.compareTo(...) нужен объект типа MyNested<T>, но other.getNested() возвращает объект типа MyNested<?>.
Если я сделаю:
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if ((obj == null) || (this.getClass() != obj.getClass())) return false;
MyClass<T> other = (MyClass<T>) obj;
return this.getNested().compareTo(other.getNested()) == 0;
}
Моя IDE жалуется:
Unchecked cast: 'java.lang.object' to 'MyClass<T>'
который я могу убрать, добавив
@SuppressWarnings("unchecked")
в строке перед приведением, но я не уверен, что это правильно, так как не верю, что проверка this.getClass() != obj.getClass() в предыдущей строке гарантирует, что общие типы одинаковы, а только что классы одинаковы.
Как правильно написать метод равенства в этом случае?
Похоже, что фундаментальная проблема заключается в том, что вложенный класс можно сравнивать только с вложенными классами с аргументом того же типа, когда вам нужно иметь возможность сравнивать вложенные экземпляры любого типа.
Собственно, зачем вообще использовать compareTo во вложенном типе вместо equals? Это было бы самое простое решение, если предположить, что equals правильно реализован во вложенном классе. Если нет, то так и должно быть: equals и compareTo всегда должны возвращать согласованные результаты, иначе вы неизбежно столкнетесь с странными ошибками.




Просто используйте equals (или служебный метод Objects.equals) вместо compareTo, например:
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
MyClass<?> other = (MyClass<?>) obj;
return Objects.equals(getNested(), other.getNested());
}
Да, это гораздо лучшее решение. Спасибо!
@AmateurLinguist Если мой ответ действительно отвечает на ваш вопрос, можете ли вы пометить его как принятый?
Привет, @jon-hason. Извините, я новичок и не знал, что это сделать. Сделанный! И еще раз спасибо!
Безопасна ли гипсовая повязка, зависит от того, как
MyNestedреализованоComparable. Пожалуйста, покажите полный, минимально воспроизводимый пример - что-то, что я могу скопировать и вставить в свою IDE и воспроизвести проблему.