如何通过运行时传入类型参数实例化泛型类TypedProducer
解决方案:运行时实例化泛型类
TypedProducer<K, V> 核心背景:Java泛型擦除
Java泛型是编译期特性,运行时泛型类型参数会被擦除,所以TypedProducer<Integer, String>和TypedProducer<Object, Object>的实例在运行时本质上是同一个类的对象。只要TypedProducer的逻辑不依赖运行时获取泛型参数的具体类型,直接实例化即可。
方案1:直接实例化(最简洁)
如果业务逻辑不需要在运行时获取K/V的类型元信息,直接通过默认构造方法创建实例即可:
public class SourceTypedClassProvider { public static TypedProducer<?, ?> instantiateTypedProducer( Class<?> keyType, Class<?> valueType) { // 泛型擦除后,运行时实例与具体泛型参数无关 return new TypedProducer<>(); } }
优化:泛型方法提升调用体验
可以把方法改成泛型方法,让调用方无需强制转换就能拿到具体类型的实例:
public class SourceTypedClassProvider { @SuppressWarnings("unchecked") public static <K, V> TypedProducer<K, V> instantiateTypedProducer( Class<K> keyType, Class<V> valueType) { return new TypedProducer<>(); } }
调用示例:
// 无需强制转换,编译期自动推断类型 TypedProducer<Integer, String> producer = SourceTypedClassProvider.instantiateTypedProducer(Integer.class, String.class);
方案2:用Guava TypeToken保留泛型元信息
如果需要在运行时保留TypedProducer<K, V>的泛型类型信息(比如后续通过反射获取K/V的具体类型),可以用Guava的TypeToken来包装泛型类型:
import com.google.common.reflect.TypeToken; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public class SourceTypedClassProvider { public static TypedProducer<?, ?> instantiateTypedProducer( Class<?> keyType, Class<?> valueType) { // 构造表示TypedProducer<K, V>的参数化类型 ParameterizedType producerType = new ParameterizedType() { @Override public Type[] getActualTypeArguments() { return new Type[]{keyType, valueType}; } @Override public Type getRawType() { return TypedProducer.class; } @Override public Type getOwnerType() { return null; } }; // 通过TypeToken实例化并保留类型信息 TypeToken<TypedProducer<?, ?>> typeToken = TypeToken.of(producerType); try { return typeToken.getRawType().getConstructor().newInstance(); } catch (Exception e) { throw new RuntimeException("Failed to instantiate TypedProducer", e); } } }
说明:
TypeToken的作用是帮你在运行时持有泛型类型的元数据,后续可以通过typeToken.getType()获取ParameterizedType,进而拿到K和V的具体类型。如果业务逻辑不需要这些元数据,方案1已经足够。
内容的提问来源于stack exchange,提问作者GoMati
相关产品推荐
相关产品推荐

