Как сделать `MyClass <String>.class` в Java?

Как вызвать public <T> T doit(Class<T> clazz); с помощью MyClass<String>.class как clazz, где я не могу создать экземпляр или расширить MyClass.

РЕДАКТИРОВАТЬ: ответы Дэвида Уинслоу и "bmargulies" верны. (MyClass<String>) doit(MyClass.class); работает для исходного вопроса. Но удивительно, когда метод возвращает MyClass<T> вместо T, кастинг больше не будет компилироваться.

Изменить: я заменил List MyClass и добавил условие к моему исходному вопросу.

Ответ 1

Используйте List.class. Из-за параметров type erasure классы Java полностью являются конструкцией времени компиляции - даже если List<String>.class был допустимым синтаксисом, это было бы точно такой же класс как List<Date>.class и т.д. Так как отражение по своей природе является средой выполнения, оно не имеет отношения к параметрам типа (как реализовано на Java).

Если вы хотите использовать объект Class для (например) экземпляра нового экземпляра List, вы можете присвоить результат этой операции для соответствующего параметра типа.

List<String> list = (List<String>)(ArrayList.class.newInstance());

Ответ 2

Я видел похожие вопросы, заданные несколько раз, например Приобретение типичного типа класса

Существуют законные основания для создания статических родовых типов. В случае "op" он, вероятно, хотел бы

MyClass<String> result = doit(MyClass<String>.class);

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

public class MyClass<T>
{
    @SuppressWarnings("unchecked")
    // may need a better method name
    static public <T2> Class<MyClass<T2>> of(Class<T2> tClass)
    {
        return (Class<MyClass<T2>>)(Class<?>)(MyClass.class);
    }
}

MyClass<String> result = doit(MyClass.of(String.class)); // no warning

Мы можем подавить предупреждение только по этому методу, убедившись, что бросок безопасен. Любой сайт вызова не увидит предупреждение.

Это все время кастинга времени компиляции. Во время выполнения все параметры типа стираются, и на самом деле пропускается только открытый объект класса. Метод of, скорее всего, будет оптимизирован, поэтому для JVM последняя строка - это ничего, кроме

MyClass result = doit(MyClass.class)

Также есть моменты, когда во время выполнения нам нужен полный тип MyClass<String>. Для представления MyClass<String> необходимо получить объект ParameterizedType.

Когда два требования объединяются вместе, то есть нам нужно выражение времени компиляции относительно MyClass и String, которое будет оцениваться во время выполнения до ParameterizedType

ParameterizedType type_MyClass_String = ???? MyClass ?? String ???

Существует метод, включающий анонимный подкласс MyClass<String>

ParameterizedType type_MyClass_String = superTypeOf( new MyClass<String>(){} );

который я нахожу довольно тревожным.

Ответ 3

См. http://jackson.codehaus.org/1.7.0/javadoc/org/codehaus/jackson/type/TypeReference.html и ссылки, которые он ссылается для всестороннего обсуждения вопросов, связанных с генериками.

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

В отличие от вашего комментария к другому ответу, вы можете написать List<List<String>> obj = (List<List<String>>) doit(List.class);, вы просто не можете избежать предупреждения при его написании.

Ответ 4

Так как после вашего обновления ваш вопрос не является точным дубликатом:

Вам нужно будет вызвать getClass() в экземпляре MyClass. Лучше иметь фиктивный статический конечный экземпляр где-то:

public static final MyClass INSTANCE = new MyClass();
...
return (Class<MyClass<String>>) instance.getClass();

Ответ 5

T соответствует List, поэтому любая ссылка на String как общий параметр List не имеет значения.

Ответ 6

Как сделать MyClass<String>.class в Java?

Вы не можете.

Дженерики в стирании типа использования Java; тип параметризованного аргумента применяется во время компиляции, но он теряется после. Полученный байт-код для экземпляра универсального класса не содержит метаданных во время выполнения.

Как и сейчас, это просто невозможно, основной дизайн языка ошибочен IMO.