Почему переопределяющие методы не могут указать параметр типа, если переопределенный метод этого не делает?

Следующий код не компилируется, однако, если я изменяю f(object) на f(String) или f (Integer), он компилируется. Я читал другие посты на эту тему, но до сих пор не понимаю, почему компилятор не знает, какой метод использовать (в случае нового экземпляра A a = new B();)

public class SampleTester { 
    public static class A {
        public void f(int x) { System.out.print("1"); } 
        public void f(Object x) { System.out.print("2"); } 
    } 
    public static class B extends A { 
           public <T> void f(T x) { System.out.print("3"); } //compiler error
    }   
    public static void main(String[] args) { 
         A a = new A();
         B b= new B(); 
         a.f(3);
         a.f("foo"); 
         b.f(3);
         b.f("foo"); 
    } 
} 

Если я изменю T x в Object t он все еще не компилируется, так в чем же разница? и кроме того, почему он не просто отменяет функцию из A? (оба имеют одинаковую подпись после стирания типа

1 ответ

Решение

Класс B продолжается A и, таким образом, наследует все методы, которые присутствуют в A, Это означает, что B будет иметь 3 метода:

public void f(int x)
public void f(Object x)
public <T> void f(T x)

Проблема в том, что f(T x) будет проходить стирание типа во время компиляции и T будет заменен на Objectчто приводит к дублированию метода, так как у вас уже есть метод, который принимает Object аргумент.

Чтобы это исправить, либо удалите метод, который принимает Object аргумент или предоставить верхнюю границу для T, (пример T extends Number чтобы T заменяется на Number во время стирания типа)


Чтобы ответить на ваш комментарий (который я сейчас добавил к вашему вопросу):

public <T> void f(Object x) не компилируется, потому что это недопустимое переопределение для public void f(Object x) от A,

Метод public <T> void f(Object x) принадлежит подклассу и может быть вызван с использованием ссылки суперкласса как a.<Integer>f(null); или же a.<String>f(null);, Поскольку переопределенные методы разрешаются во время выполнения, но обобщенные типы проходят стирание типов во время самой компиляции, компилятор не может узнать, следует ли заменить T с Integer или же String во время компиляции.

Все еще законно повернуть методы так, чтобы у вас был метод public <T> void f(Object x) в A и метод public void f(Object x) в B так как у компилятора есть вся информация, необходимая, чтобы решить, что <T> следует заменить на.

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