如何使用
示例1
package org.example;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.Data;
import org.junit.jupiter.api.Test;
import java.util.List;
public class TestTypeToken {
@Data
public static class UserInfo {
private String name;
}
@Data
public static class DataHolder<T> {
private T data;
}
@Test
public void test_01() {
TypeToken typeToken = new TypeToken<Long>(){};
System.out.println("getType: " + typeToken.getType());
// 以上代码输出: getType: class java.lang.Long
System.out.println("getRawType: " + typeToken.getRawType());
// 以上代码输出: getRawType: class java.lang.Long
}
@Test
public void test_02() {
TypeToken typeToken = new TypeToken<List<Long>>(){};
System.out.println("getType: " + typeToken.getType());
// 以上代码输出: getType: java.util.List<java.lang.Long>
System.out.println("getRawType: " + typeToken.getRawType());
// 以上代码输出: getRawType: interface java.util.List
}
@Test
public void test_03() {
TypeToken typeToken = new TypeToken<List<Long>>(){};
Gson gson = new Gson();
List<Long> list = gson.fromJson("[1,2,34]", typeToken.getType());
System.out.println("list: " + list);
// 以上代码输出: list: [1, 2, 34]
}
@Test
public void test_04() {
TypeToken typeToken = new TypeToken<DataHolder<Long>>(){};
System.out.println("getType: " + typeToken.getType());
// 以上代码输出: getType: org.example.TestTypeToken$DataHolder<java.lang.Long>
System.out.println("getRawType: " + typeToken.getRawType());
// 以上代码输出: getRawType: class org.example.TestTypeToken$DataHolder
Gson gson = new Gson();
DataHolder<Long> result = gson.fromJson("{\"data\": 123}", typeToken.getType());
System.out.println("result: " + result);
// 以上代码输出: result: TestTypeToken.DataHolder(data=123)
}
}
源码分析: 如何获取泛型变量的实际类型
这里不分析 TypeToken 的代码,我们自己写个实现。原理是类似的。
示例1
package org.example;
import lombok.Data;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
public class TestTypeToken02 {
@Data
public static class DataHolder<T> {
private T data;
}
public static class MyTypeToken<T> {
}
@Test
public void test() throws NoSuchFieldException {
// 生成 MyTypeToken 的匿名子类
MyTypeToken myTypeToken = new MyTypeToken<DataHolder<String>>(){};
// 获取 myTypeToken 父类
Type type = myTypeToken.getClass().getGenericSuperclass();
// 下面的代码输出: org.example.TestTypeToken02$MyTypeToken<org.example.TestTypeToken02$DataHolder<java.lang.String>>
System.out.println(type);
assert type instanceof ParameterizedType;
ParameterizedType parameterizedType = (ParameterizedType) type;
assert parameterizedType.getActualTypeArguments().length == 1;
// 获取 MyTypeToken<DataHolder<String>> 中的 DataHolder<String> 类型信息
Type dataHolderType = parameterizedType.getActualTypeArguments()[0];
assert dataHolderType instanceof ParameterizedType;
ParameterizedType dataHolderParameterizedType = (ParameterizedType) dataHolderType;
// 以下代码输出: org.example.TestTypeToken02$DataHolder<java.lang.String>
System.out.println(dataHolderParameterizedType);
assert dataHolderParameterizedType.getRawType() == DataHolder.class;
// 获取 data 字段
Field dataField = ((Class)dataHolderParameterizedType.getRawType()).getDeclaredField("data");
Type dataFieldGenericType = dataField.getGenericType();
assert dataFieldGenericType instanceof TypeVariable;
// 获取 data 字段的泛型类型,在类的泛型参数列表中的位置
TypeVariable dataFieldTypeVariable = (TypeVariable) dataFieldGenericType;
TypeVariable[] typeVariableArray = ((Class<?>) dataHolderParameterizedType.getRawType()).getTypeParameters();
int index = -1;
for (int i = 0; i < typeVariableArray.length; i++) {
if (dataFieldTypeVariable == typeVariableArray[i]) {
index = i;
}
}
assert index != -1;
// 找到泛型变量的真实类型
Type dataFieldRealType = dataHolderParameterizedType.getActualTypeArguments()[index];
assert dataFieldRealType == String.class;
// 下面的代码输出: data 字段的真实类型是: class java.lang.String
System.out.println("data 字段的真实类型是: " + dataFieldRealType);
}
}
示例2
package org.example;
import lombok.Data;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
public class TestTypeToken02 {
@Data
public static class DataHolder<T, S> {
private T data01;
private S data02;
private T data03;
}
public static class MyTypeToken<T> {
}
@Test
public void test() throws NoSuchFieldException {
// 生成 MyTypeToken 的匿名子类
MyTypeToken myTypeToken = new MyTypeToken<DataHolder<String, Integer>>(){};
// 获取 myTypeToken 父类
Type type = myTypeToken.getClass().getGenericSuperclass();
assert type instanceof ParameterizedType;
ParameterizedType parameterizedType = (ParameterizedType) type;
assert parameterizedType.getActualTypeArguments().length == 1;
// 获取 MyTypeToken<DataHolder<String>> 中的 DataHolder<String> 类型信息
Type dataHolderType = parameterizedType.getActualTypeArguments()[0];
assert dataHolderType instanceof ParameterizedType;
ParameterizedType dataHolderParameterizedType = (ParameterizedType) dataHolderType;
assert dataHolderParameterizedType.getRawType() == DataHolder.class;
// 便利字段
for (Field field : ((Class)dataHolderParameterizedType.getRawType()).getDeclaredFields()) {
// 获取 data 字段
Type fieldGenericType = field.getGenericType();
assert fieldGenericType instanceof TypeVariable;
// 获取 data 字段的泛型类型,在类的泛型参数列表中的位置
TypeVariable fieldTypeVariable = (TypeVariable) fieldGenericType;
TypeVariable[] typeVariableArray = ((Class<?>) dataHolderParameterizedType.getRawType()).getTypeParameters();
int index = -1;
for (int i = 0; i < typeVariableArray.length; i++) {
if (fieldTypeVariable == typeVariableArray[i]) {
index = i;
}
}
assert index != -1;
// 找到泛型变量的真实类型
Type dataFieldRealType = dataHolderParameterizedType.getActualTypeArguments()[index];
// 下面的代码输出: data 字段的真实类型是: class java.lang.String
System.out.printf("字段名: %s, 泛型类型: %s, 真实类型: %s%n", field.getName(), fieldTypeVariable, dataFieldRealType);
}
}
}
执行结果:
字段名: data01, 泛型类型: T, 真实类型: class java.lang.String
字段名: data02, 泛型类型: S, 真实类型: class java.lang.Integer
字段名: data03, 泛型类型: T, 真实类型: class java.lang.String
示例3
package org.example;
import lombok.Data;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.List;
public class TestTypeToken02 {
@Data
public static class DataHolder<T> {
private List<String> data01;
private List<T> data02;
}
public static class MyTypeToken<T> {
}
@Test
public void test() throws NoSuchFieldException {
// 生成 MyTypeToken 的匿名子类
MyTypeToken myTypeToken = new MyTypeToken<DataHolder<String>>(){};
// 获取 myTypeToken 父类
Type type = myTypeToken.getClass().getGenericSuperclass();
assert type instanceof ParameterizedType;
ParameterizedType parameterizedType = (ParameterizedType) type;
assert parameterizedType.getActualTypeArguments().length == 1;
// 获取 MyTypeToken<DataHolder<String>> 中的 DataHolder<String> 类型信息
Type dataHolderType = parameterizedType.getActualTypeArguments()[0];
assert dataHolderType instanceof ParameterizedType;
ParameterizedType dataHolderParameterizedType = (ParameterizedType) dataHolderType;
assert dataHolderParameterizedType.getRawType() == DataHolder.class;
// 遍历字段
for (Field field : ((Class)dataHolderParameterizedType.getRawType()).getDeclaredFields()) {
System.out.println("---- 处理字段: " + field.getName());
Type fieldGenericType = field.getGenericType();
System.out.println(fieldGenericType);
if (fieldGenericType instanceof ParameterizedType) {
System.out.println("该字段是 ParameterizedType,下面尝试获取该字段的类型和类型参数的实际类型");
ParameterizedType fieldParameterizedType = (ParameterizedType) fieldGenericType;
System.out.println("rawType: " + fieldParameterizedType.getRawType());
System.out.println("开始遍历类型参数");
for (Type typeArg : fieldParameterizedType.getActualTypeArguments()) {
if (typeArg instanceof Class) {
System.out.println("类型参数: " + typeArg);
}
else if (typeArg instanceof TypeVariable) {
TypeVariable typeArgTypeVariable = (TypeVariable) typeArg;
TypeVariable[] typeVariableArray = ((Class<?>) dataHolderParameterizedType.getRawType()).getTypeParameters();
int index = -1;
for (int i = 0; i < typeVariableArray.length; i++) {
if (typeArgTypeVariable == typeVariableArray[i]) {
index = i;
}
}
assert index != -1;
// 找到泛型变量的真实类型
Type typeArgRealType = dataHolderParameterizedType.getActualTypeArguments()[index];
System.out.printf("类型参数: %s, 实际类型: %s\n", typeArg, typeArgRealType);
}
else {
System.out.println("其他情况: " + typeArg);
}
}
}
}
}
}
执行结果:
---- 处理字段: data01
java.util.List<java.lang.String>
该字段是 ParameterizedType,下面尝试获取该字段的类型和类型参数的实际类型
rawType: interface java.util.List
开始遍历类型参数
类型参数: class java.lang.String
---- 处理字段: data02
java.util.List<T>
该字段是 ParameterizedType,下面尝试获取该字段的类型和类型参数的实际类型
rawType: interface java.util.List
开始遍历类型参数
类型参数: T, 实际类型: class java.lang.String