Question 1:
Suggest I have a example like this:
public <T> void methodA(T req) { // doSth } psvm(){ ClassA aClass = new ClassA(); aClass.<String>methodA("hello world"); }
then can I get type String
in methodA
without actually passing String
to it?
Question 2:
If the previous example is transformed to this:
public <T> void methodA(Predicate<T> req) { // doSth } psvm(){ ClassA aClass = new ClassA(); aClass.<String>methodA(item -> "hello world".equals(item)); }
I mean what was passed into methodA
is no more a simple object but a lambda expression, also, can I get type String
in methodA
?
Advertisement
Answer
No, it is not possible to determine the generic type of a generic method, due to type erasure. At compile time, the generic type of the method is discarded, and there is no way to get this information at runtime.
public class ClassA { public <T> void methodA(T req) { Class<T> genericType = ?; // Impossible to get e.g. Class<String> // [...] } public static void main(){ new ClassA().methodA("hello world"); } }
There are certain scenarios where generic type information is retained (such as extending a generic class with a specific generic type, e.g. class MyList implements List<String>
). However, there is no way to do so for a generic method.
The best you could do, if you needed that information, would be to pass it in (which you stated you didn’t want to do):
public <T> void methodA(T req, Class<T> type) { // [...] }
Another option, if all you needed was the type of the object passed in as opposed to the type of the generic method, would be to get the class of the object.
public <T> void methodA(T req) { Class<?> type = req.getClass(); // Assuming req is non-null // [...] }
Note that with this option in this specific example, the generic type is no longer being used for anything, so it can be dropped from the method signature. This may not always be the case, such as if multiple parameters or a parameter and the return type needed matching generic types.
public void methodA(Object req)