当使用反射获取到一个Type时
可能会是以下几种类型:
1.Class (eg:普通Class或者数组Class)
public class UserService {
public User[] getUserArray() {
return null;
}
}
@Test
public void getUserArrayTest() throws NoSuchMethodException {
Class<?> clazz = UserService.class;
Method method = clazz.getMethod("getUserArray");
//获取返回值类型
Type type = method.getGenericReturnType();
System.out.println("type is class?: " + (type instanceof Class));
if (type instanceof Class<?>) {
System.out.println("type:" + type);
System.out.println("type is Array?: " + (((Class<?>) type).isArray()));
}
}
控制台输出:
type is class?: true
type:class [Lcom.valsong.reflect.User;
type is Array?: true
可以看到 getUserArray()方法的返回值类型User[]是一个Class并且是一个数组类型
ps:如何使用反射创建数组实例?
使用
User[] users = User[].class.newInstance();
的方式是行不通的 执行上述代码会得到一个错误:
Caused by: java.lang.NoSuchMethodException: [Lcom.valsong.reflect.User;.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
... 23 more
正确方式:
@Test
public void createArrayInstanceTest() throws IllegalAccessException, InstantiationException {
User[] users = (User[]) Array.newInstance(User.class, 10);
users[0] = new User("val", 26);
System.out.println(Arrays.toString(users));
}
2.ParameterizedType (eg:List<User> Map<String,User> 等)
public List<User> findAll() {
return Collections.emptyList();
}
@Test
public void findAllTest() throws NoSuchMethodException {
Class<?> clazz = UserService.class;
Method method = clazz.getMethod("findAll");
//获取返回值类型
Type type = method.getGenericReturnType();
System.out.println("type is ParameterizedType?: " + (type instanceof ParameterizedType));
if (type instanceof ParameterizedType) {
Type rawType = ((ParameterizedType) type).getRawType();
Type [] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
System.out.println("rawType: " + rawType);
System.out.println("actualTypeArguments:" + Arrays.toString(actualTypeArguments));
}
}
findAll()方法返回值List<User>类型就是ParameterizedType
控制台输出:
type is ParameterizedType?: true
rawType: interface java.util.List
actualTypeArguments:[class com.valsong.reflect.User]
注意当List没有泛型时他的类型就是class,例如
public List findAll2() {
return Collections.emptyList();
}
@Test
public void findAll2Test() throws NoSuchMethodException {
Class<?> clazz = UserService.class;
Method method = clazz.getMethod("findAll2");
//获取返回值类型
Type type = method.getGenericReturnType();
System.out.println("type is ParameterizedType?: " + (type instanceof ParameterizedType));
System.out.println("type is class?: " + (type instanceof Class));
}
控制台输出:
type is ParameterizedType?: false
type is class?: true
3.WildcardType (eg: ? , ? extends User , ? super User 等)
public List<?> findAll3() {
return Collections.emptyList();
}
@Test
public void findAll3Test() throws NoSuchMethodException {
Class<?> clazz = UserService.class;
Method method = clazz.getMethod("findAll3");
//获取返回值类型
Type type = method.getGenericReturnType();
System.out.println("type is ParameterizedType?: " + (type instanceof ParameterizedType));
if (type instanceof ParameterizedType) {
Type rawType = ((ParameterizedType) type).getRawType();
Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
System.out.println("rawType: " + rawType);
System.out.println("actualTypeArguments:" + Arrays.toString(actualTypeArguments));
System.out.println("actualTypeArguments[0] is WildcardType?: " + (actualTypeArguments[0] instanceof WildcardType));
}
}
控制台输出:
type is ParameterizedType?: true
rawType: interface java.util.List
actualTypeArguments:[?]
actualTypeArguments[0] is WildcardType?: true
findAll3()的返回值List<?>其中?就是WildcardType
当然类似
public List<? extends User> findAll4() {
return Collections.emptyList();
}
public List<? super User> findAll5() {
return Collections.emptyList();
}
同理,? extends User , ? super User 也是WildcardType
4.TypeVariable (eg: T)
public class UserService extends AbstractService<User> {
}
public class AbstractService<T> {
void save(T t) {
}
}
@Test
public void saveTest() throws NoSuchMethodException {
Class<?> clazz = UserService.class;
Method method = clazz.getMethod("save", Object.class);
//获取返回值类型
Type[] types = method.getGenericParameterTypes();
Type type = types[0];
System.out.println("type is TypeVariable?: " + (type instanceof TypeVariable));
if (type instanceof TypeVariable) {
System.out.println("type:" + type);
Class<?> genericDeclaration = (Class<?>) ((TypeVariable) type).getGenericDeclaration();
TypeVariable<?>[] typeVariables = genericDeclaration.getTypeParameters();
System.out.println(Arrays.toString(typeVariables));
ParameterizedType genericSuperclzz = (ParameterizedType) clazz.getGenericSuperclass();
Type[] actualTypeArguments = genericSuperclzz.getActualTypeArguments();
System.out.println(Arrays.toString(actualTypeArguments));
int index = 0;
for (int i = 0; i < typeVariables.length; i++) {
if (type.equals(typeVariables[i])) {
index = i;
break;
}
}
System.out.println("real type is : "+actualTypeArguments[index]);
}
}
控制台输出:
type is TypeVariable?: true
type:T
[T]
[class com.valsong.reflect.User]
real type is : class com.valsong.reflect.User
save(T t)方法的参数T类型就是TypeVariable
要想获得T真正的类型则需要找出 type在 typeVariables 中的下标
再通过下标去actualTypeArguments中获取真正的类型
5.GenericArrayType (eg:T[] )
public class UserService extends AbstractService<User> {
}
public class AbstractService<T> {
public T[] getAll() {
return null;
}
}
@Test
public void getAllTest() throws NoSuchMethodException {
Class<?> clazz = UserService.class;
Method method = clazz.getMethod("getAll");
//获取返回值类型
//获取返回值类型
Type type = method.getGenericReturnType();
System.out.println("type is GenericArrayType?: " + (type instanceof GenericArrayType));
if (type instanceof GenericArrayType) {
System.out.println("type:" + type);
Type genericComponentType = ((GenericArrayType) type).getGenericComponentType();
System.out.println("genericComponentType: " + genericComponentType);
Class<?> genericDeclaration = (Class<?>) ((TypeVariable) genericComponentType).getGenericDeclaration();
TypeVariable<?>[] typeVariables = genericDeclaration.getTypeParameters();
System.out.println(Arrays.toString(typeVariables));
ParameterizedType genericSuperclzz = (ParameterizedType) clazz.getGenericSuperclass();
Type[] actualTypeArguments = genericSuperclzz.getActualTypeArguments();
System.out.println(Arrays.toString(actualTypeArguments));
int index = 0;
for (int i = 0; i < typeVariables.length; i++) {
if (type.equals(typeVariables[i])) {
index = i;
break;
}
}
System.out.println("real genericComponentType is : " + actualTypeArguments[index]);
Class<?> realType = Array.newInstance((Class<?>) actualTypeArguments[index], 0).getClass();
System.out.println("real type is : " + realType);
}
}
控制台输出:
type is GenericArrayType?: true
type:T[]
genericComponentType: T
[T]
[class com.valsong.reflect.User]
real genericComponentType is : class com.valsong.reflect.User
real type is : class [Lcom.valsong.reflect.User;
getAll()方法的返回值T[]类型是GenericArrayType
首先获取type为T[]
然后获取genericComponentType为T
genericComponentType在 typeVariables 中的下标
再通过下标去actualTypeArguments中获取真正的类型为 class com.valsong.reflect.User
最后通过手动创建一个空数组的实例来获取realType为class [Lcom.valsong.reflect.User