Можно ли определить generics тип класса

190
10 ноября 2017, 07:28

Есть класс:

class<T> {
}

Можно ли как-то определить тип Т, не передавая его в конструктор?

Answer 1

Дженерики существуют только на момент компиляции, в рантайме, когда приложение выполняется информации о дженериках стирается. Тип дженерика нельзя определить ни через мета информацию о полях класса, ни через метаинформацию о методах класса(принимаемые параметры, возвращаемый тип). Так же в java нельзя создать инстанс дженеричной переменной. Следовательно получить тип дженеричной переменной класса, не имея ее инстанса невозможно.

Если у вас есть возможность получить инстанс переменной-дженерика(через рефлексию), то его тип можно определить не передавая его в конструктор, иначе ответ нет, нельзя.

Answer 2

На самом деле, можно используя рефлексию и getGenericSuperclass / getGenericInterfaces / getTypeParameters (хотя и считается, что информация о дженериках в Java стирается), но крайне не рекомендуется (рефлексия и все дела, к тому же не уверен, что этот фокус будет работать во всех случаях и на любой JVM). Проверьте следующий код:

public class TestClass {
    class MyClass extends OtherClass<GenericClass>{
        String myName;
        //Whatever
    }
    class OtherClass<T> {
        T myfield;
    }
    class GenericClass {
        String field;
    }
    public static void main(String[] args){
       OtherClass<GenericClass> ttt = new MyClass();
       ParameterizedType t = (ParameterizedType) ttt.getClass().getGenericSuperclass();
       Class<?> cls = (Class<?>) t.getActualTypeArguments()[0]; //
       System.out.println(cls);  // напечатает TestClass#GenericClass
    }    
}

Обычно намного проще и быстрее просто передавать параметр Class cls в нужную функцию. Более того будет работать даже такой код (проверьте)

    Object ttt = new MyClass();
    ParameterizedType t = (ParameterizedType) ttt.getClass().getGenericSuperclass();
    Class<?> cls = (Class<?>) t.getActualTypeArguments()[0]; 
    System.out.println(cls); // напечатает TestClass#GenericClass

Можно так же узнать generic даже если нет child'а, например так

    Object ttt = new OtherClass<GenericClass>();
    TypeVariable[] a1 = ttt.getClass().getTypeParameters();
    System.out.println(a1[0].getGenericDeclaration()); // напечатает TestClass#GenericClass

Мало кто знает, что миф о том что информация о generic теряется всегда и в любой JVM уже не актуален, другое дело стоит ли использовать настолько черную магию?

READ ALSO
Как правильно использовать Fork/Join Framework в Java?

Как правильно использовать Fork/Join Framework в Java?

I write simple program with Fork/Join FrameworkFor first version of my program, that not working correct, I used the book "Herbert Shield

217
Работа с GET/POST и брузером

Работа с GET/POST и брузером

Нужно реализовать такой функционал для входа в приложение через twitchПользователь в приложении (написанном на JavaFx) нажимает кнопку Login, открывается...

195
Выделить произвольную область кода. IntelliJ IDEA 2017.2.5

Выделить произвольную область кода. IntelliJ IDEA 2017.2.5

Как выделить какую-то произвольную область кода в IDE IntelliJ IDEA 20172

186
Ключевое слово &ldquo;is&rdquo;

Ключевое слово “is”

Подскажите почему возникают ошибки

189