Невозможно сделать статическую ссылку на общий подкласс (Java) - PullRequest
5 голосов
/ 24 марта 2009

У меня есть следующий код:

class SuperClass {
    public static String getName() { return "super"; }
}

class SubClass extends SuperClass {
    public static String getName() { return "sub"; }
}

public class Dummy<T extends SuperClass> {
    public void print() {
        System.out.println("SuperClass: " + SuperClass.getName());
        System.out.println("SubClass: " + SubClass.getName());
        System.out.println("T: " + T.getName());
    }
    public static void main(String[] args) {
        new Dummy<SubClass>().print();
    }
}

Этот код выводит следующее:

SuperClass: super
SubClass: sub
T: super

Мой вопрос: Почему T.getName () не возвращает значение SubClass.getName ()? В конце концов, я указал, что T == SubClass. Или вызовы статических функций недопустимы для общих ссылок?

Заранее большое спасибо!

Ответы [ 3 ]

13 голосов
/ 24 марта 2009

Это не просто проблема дженериков.

Если вы скажете:

SuperClass obj = new SubClass();
System.out.println(obj.getName());

вы также получите "супер". Не существует "полиморфных" статических методов.

В вашем случае все, что знает компилятор о T, это то, что он расширяет SuperClass, поэтому он будет вызывать SuperClass.getName().

1 голос
/ 24 марта 2009

В отличие от шаблонов C ++, шаблоны Java работают по типу стирания, поэтому он генерирует только один класс для всех значений T и преобразует все ссылки на тип T в этом классе в супер тип T в в этом случае SuperClass, затем используется виртуальная диспетчеризация для предоставления дисперсии для вызовов методов объекта и статическая диспетчеризация для вызовов статических методов.

Поэтому, когда вы делаете Dummy<SubClass>.print(), компилятор не выполняет глобальную замену T на SubClass в Dummy. Все, что делает компилятор, проверяет, использует ли T в качестве аргумента или возвращаемого типа в методах Dummy значение SubClass. Никаких изменений внутри кода Dummy нет, поэтому тот же самый статический метод SuperClass вызывается независимо от того, что T.

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

0 голосов
/ 24 марта 2009

Когда вы создали экземпляр класса с помощью «new Dummy ()», вы вызвали конструктор по умолчанию, который фактически ничего не устанавливает. Когда был вызван метод print, виртуальная машина увидела, что тип T, объявленный в объявлении класса, является SuperClass; Затем он вызывает статический метод для этого класса.

...