Получить "настоящий" класс родового типа

Как я могу получить "настоящий" класс общего типа?

Пример:

public class MyClass<T> {
    public void method(){
        //something

        System.out.println(T.class) //causes a compile error, I wont the class name

        //something
    }
}

Если T = целое число

Вывод:

java.lang.Integer

Если T = String

Вывод:

java.lang.String

Спасибо

Ответ 1

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

public class Test<T> {

    T var;

    public static void main(String[] args) {
        Test<Integer> a = new Test<Integer>();
        System.out.println(a.boo());
        a.setVar(new Integer(10));
        System.out.println(a.boo());
    }

    public String boo() {
        if (var == null) {
            return "Don't know yet";
        }
        return var.getClass().getSimpleName();
    }

    public void setVar(T var) {
        this.var = var;
    }

    public T getVar() {
        return var;
    }
}

Ответ 2

Вы не можете. Информация удаляется из кода во время компиляции, процесс, известный как стирание типа. Подробнее см. Здесь Тип Erasure

Изменить: извините, мой плохой, информация не загружается во время выполнения.

Ответ 3

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

public class MyClass<T> {
    public void method(Class<T> clazz) {
        // something

        System.out.println(clazz.getName());

        // something
    }
}

и вы используете его как это

new MyClass<String>().method(String.class);

Ответ 4

В случае вашей ситуации вы не можете. Тем не менее, вы можете использовать токены Super Type для этого типа вещей: http://gafter.blogspot.com/2006/12/super-type-tokens.html

Примером реализации является класс TypeReference библиотеки обработки Jackson json.

Это продвинутый материал и, вероятно, больше, чем вы хотели знать; -)

Ответ 5

Обратите внимание, что подходы, основанные на 'getClass()' на экземпляре, полученном с помощью универсального типа, получат фактический тип этого объекта, что не обязательно является общим типом - это будет тот тип, по которому вызывающий пользователь знал экземпляр.

Например, рассмотрим случай, когда вызывающий объект обрабатывает объект интерфейсом; при переходе к родовым конструкциям общий тип будет интерфейсом, а не фактическим классом экземпляра.

Рассмотрим следующий пример класса "Пара", который позволяет возвращать две ссылки на объекты через POJO:

public class Pair<U,V>
{
    public final U first;
    public final V second;
    public static <U,V> Pair<U,V> of (U first, V second)
    {
        return new Pair<U,V> (first, second);
    }
    protected Pair (U first, V second)
    {
        this.first  = first;
        this.second = second;
    }
}

Мы рассматривали, как изменить функцию "Pair.of()" factory, чтобы вернуть производный класс Comparable Pair, если U и V были сопоставимыми. Однако, хотя мы можем определить, сопоставимы ли "первый" и "второй" с использованием instanceof, мы не знаем, что сами U и V являются сопоставимыми.

Чтобы это сработало, точный тип пары, возвращаемый параметром Pair.of(), должен зависеть от общих типов, а не от фактических типов аргументов.