Метод Equals с приведением универсального параметризованного класса

Я использую 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() в предыдущей строке гарантирует, что общие типы одинаковы, а только что классы одинаковы.

Как правильно написать метод равенства в этом случае?

Безопасна ли гипсовая повязка, зависит от того, как MyNested реализовано Comparable. Пожалуйста, покажите полный, минимально воспроизводимый пример - что-то, что я могу скопировать и вставить в свою IDE и воспроизвести проблему.

Sweeper 24.05.2024 05:00

Похоже, что фундаментальная проблема заключается в том, что вложенный класс можно сравнивать только с вложенными классами с аргументом того же типа, когда вам нужно иметь возможность сравнивать вложенные экземпляры любого типа.

Tim Moore 24.05.2024 05:18

Собственно, зачем вообще использовать compareTo во вложенном типе вместо equals? Это было бы самое простое решение, если предположить, что equals правильно реализован во вложенном классе. Если нет, то так и должно быть: equals и compareTo всегда должны возвращать согласованные результаты, иначе вы неизбежно столкнетесь с странными ошибками.

Tim Moore 24.05.2024 05:22
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Просто используйте 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());
}

Да, это гораздо лучшее решение. Спасибо!

Amateur Linguist 27.05.2024 02:59

@AmateurLinguist Если мой ответ действительно отвечает на ваш вопрос, можете ли вы пометить его как принятый?

jon hanson 27.05.2024 05:46

Привет, @jon-hason. Извините, я новичок и не знал, что это сделать. Сделанный! И еще раз спасибо!

Amateur Linguist 29.05.2024 01:17

Другие вопросы по теме