Ошибка столкновения имени Java, метод имеет то же самое стирание, что и другой метод

У меня есть два класса следующим образом

Класс QueryResult:

public class QueryResult
{
...
public static List sortResults(boolean ascending, List<QueryResult> toSort)
    {   ...
    }
}

и класс CaseResult:

public class CaseResult extends QueryResult
{
...
public static List sortResults(boolean ascending, List<CaseResult> toSort)
    {   ...
    }
}

Я получаю следующую ошибку:

Конфликт имен: метод sortResults(boolean, List) типа CaseResult имеет такое же стирание, что и sortResults(boolean, List) типа QueryResult, но не скрывает его CaseResult.java

Я попробовал ответить на аналогичный вопрос: clash name generics, такое же стирание, но получил больше ошибок. Я думаю, что могу что-то неправильно понять, или эти ответы не подходят для моего случая.

Может ли кто-нибудь предоставить какие-либо решения или объяснить больше, чтобы помочь мне понять? Спасибо вам всем.

2 ответа

Решение

Согласно документации Java,

Если подкласс определяет статический метод с той же сигнатурой, что и статический метод в суперклассе, то метод в подклассе скрывает метод в суперклассе.

Различие между сокрытием статического метода и переопределением метода экземпляра имеет важные последствия:

  • Версия переопределенного метода экземпляра, который вызывается, является той из подкласса.
  • Версия скрытого статического метода, который вызывается, зависит от того, вызывается ли он из суперкласса или из подкласса.

Причина ошибки кроется в ответе Даршита Чокши. Однако, поскольку решение / альтернатива еще не опубликовано, попробуйте следующее:

Вы пытаетесь переопределить метод sortResults() таким образом, чтобы можно было сортировать списки с различными элементами. Однако при переопределении необходимо иметь одинаковую сигнатуру типа. Сигнатура в вашем случае выглядит аналогично, но поскольку элементы в List различаются - компилятор понимает, что List и List различны, но из-за стирания типа в Java было бы неясно, какой метод он должен вызывать - т.е. должен ли он вызывать метод суперкласса или метод подкласса.

Вместо переопределения, вместо этого измените оригинальный метод в суперклассе (в вашем случае, QueryResult), чтобы он мог обрабатывать любой тип элемента List. Вы можете использовать подстановочный знак для достижения этой цели:

public class QueryResult {
...
public <T> static List<T> sortResults(boolean ascending, List<T> toSort) {   
    ...
    }
}

Этот метод получает список и выводит тип элемента, назначая тип элемента параметру универсального типа T. Всякий раз, когда вы захотите обратиться к типу элемента в теле метода, вместо использования имени типа элемента (ранее QueryResult или CaseResult), теперь вместо этого вы должны использовать переменную универсального типа T.

Вы также можете установить дополнительные границы для этой переменной, если это необходимо (т. Е. Если элемент списка должен быть подтипом QueryResult, вы можете сказать, что ), это заставит Java выполнить проверку типа в списке и тип элементы, которые он может иметь.

Еще один комментарий к вашему оригинальному коду. Будьте очень осторожны с использованием необработанных типов в новом универсальном коде - вы возвращаете список в виде необработанного типа: List без указания типа элемента списка, т.е. параметризованного типа: List. Это может вызвать много проблем и не рекомендуется. Создатели Java сохранили эту форму кодирования в Java для обратной совместимости кода, существовавшего до дженериков, но настоятельно рекомендуется не кодировать таким образом для нового написанного кода.

Вы можете узнать больше о необработанном типе и параметризованном типе, а также о подводных камнях использования необработанных типов, а также дополнительную информацию о захвате и границах подстановочных знаков в учебнике:

Effective Java, by Joshua Bloch
    Section: Generics
    Item 23: Don't use raw types in new code
    Item 28: Use bounded wildcards to increase API flexibility
Другие вопросы по тегам