#java #generics
#java #общие типы
Вопрос:
Мой вопрос касается переменных типа, используемых в универсальных классах и методах.
Почему мы не можем сделать что-то подобное T = new T();
или, другими словами, почему мы не можем создать объект типа variable ?
Я знаю, что общая информация стирается во время компиляции, и все преобразуется в
объект, так почему компилятор не предполагает, что это T
объект, и не позволяет нам его сконструировать?
Комментарии:
1. Это хороший вопрос. Это иллюстрирует некоторые недостатки, присущие Java Generics, и некоторые утечки в абстракции. Кстати, вы также не можете создать массив
T[]
по той же причине — удаление типа.
Ответ №1:
Проблема в том, что во время выполнения JVM не знает, какой класс T
на самом деле обозначает (эта информация не сохраняется во время выполнения, вот что означает «удаление типа»). Поэтому JVM просто видит, что вы хотите создать новый T
, но понятия не имеет, какой конструктор на самом деле вызывать — следовательно, это запрещено.
Существуют обходные пути, но они не будут работать так, как вы предлагаете.
почему компилятор не предполагает, что T является объектом, и не позволяет нам его сконструировать??
Ну, конечно, среда выполнения могла бы просто создать экземпляр java.lang.Object
для вас, но это не очень помогло бы, так как вы действительно хотели T
.
Комментарии:
1. во-первых, видит ли среда выполнения T или Object, не стирается ли общая информация, ??
2. Я не знаю, что «видит» среда выполнения, поскольку я не знаю, как это реализовано внутренне. Я полагаю, что он просто не видит вообще никакого типа. Вероятно, можно провести различие между случаями, когда в коде действительно записан «Объект», и случаями, когда тип был удален.
Ответ №2:
В дополнение к ответу слеске; если вам нужно создать объекты типа T внутри вашего универсального класса, решение состоит в том, чтобы передать Class<T>
ссылку в качестве аргумента либо конструктору, либо методу, которому необходимо создать новые объекты, и использовать этот класс для создания новых экземпляров.
Комментарии:
1. Да, это то, что я имел в виду, говоря «существуют обходные пути». Спасибо, что добавили это :-).
2. Я не одобряю этот подход, но если вам нравится писать действительно хакерский код, вы все равно можете обойти его с помощью отражения.
((ParametrizedType)getClass()).getActualTypeArguments()[0].createNewInstance()
. Это предполагает, конечно, конструктор по умолчанию.