Ta reguła ma na celu uniknięcie konfliktów w starszym kodzie, który nadal używa typów raw.
Oto przykład, dlaczego nie było to dozwolone, zaczerpnięty z JLS. Załóżmy, że przed wprowadzeniem generics do Javy napisałem taki kod:
class CollectionConverter {
List toList(Collection c) {...}
}
Rozszerzasz moją klasę w ten sposób:
class Overrider extends CollectionConverter{
List toList(Collection c) {...}
}
Po wprowadzeniu ogólnych, postanowiłem zaktualizować swoją bibliotekę.
class CollectionConverter {
<T> List<T> toList(Collection<T> c) {...}
}
Nie jesteś gotowy na żadne aktualizacje, więc zostaw Overriderklasę w spokoju. Aby poprawnie przesłonić toList()metodę, projektanci języków zdecydowali, że typ surowy jest „zastępujący odpowiednik” dla dowolnego generowanego typu. Oznacza to, że chociaż podpis twojej metody nie jest już formalnie równy podpisowi mojej nadklasy, twoja metoda wciąż zastępuje.
Teraz czas mija i decydujesz, że jesteś gotowy, aby zaktualizować swoją klasę. Ale trochę spieprzysz i zamiast edytować istniejącą, surową toList()metodę, dodajesz nową metodę taką:
class Overrider extends CollectionConverter {
@Override
List toList(Collection c) {...}
@Override
<T> List<T> toList(Collection<T> c) {...}
}
Z powodu zastąpienia równoważności typów surowych obie metody są w prawidłowej formie, aby zastąpić toList(Collection<T>)metodę. Ale oczywiście kompilator musi rozwiązać jedną metodę. Aby wyeliminować tę dwuznaczność, klasy nie mogą mieć wielu metod, które są równoważne z nadpisaniem - to znaczy wielu metod z tymi samymi typami parametrów po skasowaniu.
Kluczem jest to, że jest to reguła językowa zaprojektowana w celu zachowania zgodności ze starym kodem używającym typów raw. Nie jest to ograniczenie wymagane przez usunięcie parametrów typu; ponieważ rozpoznawanie metod zachodzi w czasie kompilacji, dodanie typów ogólnych do identyfikatora metody byłoby wystarczające.