Це правило призначене для уникнення конфліктів у застарілому коді, який все ще використовує необроблені типи.
Ось ілюстрація того, чому цього не було дозволено, накреслено з JLS. Припустимо, перед тим, як дженерики були представлені на Java, я написав такий код, як цей:
class CollectionConverter {
List toList(Collection c) {...}
}
Ви розширюєте мій клас так, як це:
class Overrider extends CollectionConverter{
List toList(Collection c) {...}
}
Після впровадження дженериків я вирішив оновити свою бібліотеку.
class CollectionConverter {
<T> List<T> toList(Collection<T> c) {...}
}
Ви не готові робити будь-які оновлення, тому ви залишаєте Overrider
клас наодинці. Щоб правильно змінити toList()
метод, мовні дизайнери вирішили, що тип "необроблений" є "еквівалентним" будь-якому узагальненому типу. Це означає, що хоча ваш підпис методу вже формально не дорівнює підпису мого суперкласу, ваш метод все одно переосмислюється.
Тепер проходить час, і ви вирішите, що готові оновити свій клас. Але ви трохи викрутите, і замість того, щоб редагувати існуючий, необроблений toList()
метод, ви додаєте новий метод на зразок цього:
class Overrider extends CollectionConverter {
@Override
List toList(Collection c) {...}
@Override
<T> List<T> toList(Collection<T> c) {...}
}
Через переоцінку еквівалентності вихідних типів обидва способи мають належну форму, щоб перекрити toList(Collection<T>)
метод. Але звичайно, компілятору потрібно вирішити єдиний метод. Щоб усунути цю неоднозначність, класам заборонено використовувати декілька методів, які є еквівалентними, тобто декілька методів із тими ж параметрами після стирання.
Ключовим є те, що це мовне правило, розроблене для підтримки сумісності зі старим кодом з використанням сировинних типів. Це не обмеження, що вимагається стиранням параметрів типу; оскільки дозвіл методу відбувається під час компіляції, додавання загальних типів до ідентифікатора методу було б достатнім.