Невозможно создать статическую ссылку на универсальный подкласс (Java)

StackOverflow https://stackoverflow.com/questions/677226

Вопрос

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

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 == подкласс.Или вызовы статических функций недопустимы для общих ссылок?

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

Это было полезно?

Решение

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

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

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

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

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

Другие советы

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top