面试题答案
一键面试可能遇到的问题
- 擦除问题:Java的泛型是通过类型擦除实现的。在运行时,泛型类型信息会被擦除,导致反射获取方法时,无法直接获取到泛型参数的具体类型。例如,对于方法
public <T> void process(T param)
,在运行时,反射获取到的方法参数类型可能只是Object
,而不是具体的泛型类型T
。 - 参数类型匹配问题:由于泛型类型擦除,在调用方法时,传入的参数类型需要手动进行匹配和转换。如果传入的参数类型与实际期望的泛型类型不匹配,可能会引发
ClassCastException
。
解决思路
- 获取泛型类型信息:可以通过获取方法的
ParameterizedType
来获取泛型类型信息。这需要通过获取包含该方法的类的Type
,并检查其是否为ParameterizedType
,然后从中获取方法的泛型参数类型。 - 类型转换和参数传递:在获取到泛型类型信息后,根据实际情况进行参数的类型转换,确保传入的参数类型与泛型类型匹配。
代码示例
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import org.junit.jupiter.api.Test;
class GenericMethodClass {
public <T> void process(T param) {
System.out.println("Processing: " + param);
}
}
public class GenericMethodReflectionTest {
@Test
public void testGenericMethodInvocation() throws Exception {
GenericMethodClass obj = new GenericMethodClass();
Class<?> clazz = obj.getClass();
Method method = clazz.getMethod("process", Object.class);
// 获取泛型类型信息
Type[] genericParameterTypes = method.getGenericParameterTypes();
if (genericParameterTypes.length > 0 && genericParameterTypes[0] instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericParameterTypes[0];
Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];
System.out.println("Actual type argument: " + actualTypeArgument);
}
// 调用方法
method.invoke(obj, "Hello, Generic Method!");
}
}
在上述代码中:
- 首先获取
GenericMethodClass
类的process
方法,由于泛型擦除,参数类型为Object
。 - 通过
getGenericParameterTypes
获取方法的泛型参数类型信息,并进行检查和处理。 - 最后通过
method.invoke
调用方法并传入参数。这样,在一定程度上解决了在反射中处理泛型方法的问题。