如何提取泛型类型的Class对象以重构CSV读取通用方法?
解决方案
核心思路:显式传入Class<T>参数
由于Java的泛型类型擦除特性,运行时无法直接从泛型参数T中获取对应的Class对象,因此最直接的解决方案是在调用方法时显式传入目标类的Class<T>实例。
重构后的CsvUtils示例
原重复方法(示例)
public List<Audi> readAudiCsv(File file) throws IOException { CsvMapper mapper = new CsvMapper(); CsvSchema schema = mapper.schemaFor(Audi.class).withHeader(); return mapper.readerFor(Audi.class).with(schema).readValue(file); } public List<BMW> readBMWCsv(File file) throws IOException { CsvMapper mapper = new CsvMapper(); CsvSchema schema = mapper.schemaFor(BMW.class).withHeader(); return mapper.readerFor(BMW.class).with(schema).readValue(file); }
通用泛型方法重构
import com.fasterxml.jackson.dataformat.csv.CsvMapper; import com.fasterxml.jackson.dataformat.csv.CsvSchema; import java.io.File; import java.io.IOException; import java.util.List; public class CsvUtils { // 通用CSV读取方法,限定T必须继承自Car public <T extends Car> List<T> readCarCsv(File file, Class<T> clazz) throws IOException { CsvMapper mapper = new CsvMapper(); // 根据传入的Class生成匹配的CSV Schema CsvSchema schema = mapper.schemaFor(clazz).withHeader(); // 基于指定Class创建Reader并完成数据读取 return mapper.readerFor(clazz).with(schema).readValue(file); } }
调用方式
// 读取Audi类型的CSV数据 List<Audi> audis = csvUtils.readCarCsv(new File("audis.csv"), Audi.class); // 读取BMW类型的CSV数据 List<BMW> bmws = csvUtils.readCarCsv(new File("bmws.csv"), BMW.class);
备选方案:使用TypeReference(适用于复杂泛型场景)
如果后续需要处理嵌套泛型等复杂结构,可以用Jackson的TypeReference来保留类型信息:
public <T extends Car> List<T> readCarCsv(File file, TypeReference<List<T>> typeRef) throws IOException { CsvMapper mapper = new CsvMapper(); // 从TypeReference中提取实际泛型类型的Class Class<?> entityClass = (Class<?>) ((ParameterizedType) typeRef.getType()).getActualTypeArguments()[0]; CsvSchema schema = mapper.schemaFor(entityClass).withHeader(); return mapper.readerFor(typeRef).with(schema).readValue(file); }
调用示例:
List<Audi> audis = csvUtils.readCarCsv(new File("audis.csv"), new TypeReference<List<Audi>>() {});
不过针对当前的简单继承场景,直接传入Class<T>的方案更简洁高效。
关键说明
- Java泛型在编译完成后会被擦除,运行时JVM无法知晓
T的具体类型,必须通过显式传递的方式提供类型信息。 - Jackson的
CsvMapper依赖明确的类型信息来完成CSV到实体类的映射,schemaFor(Class)和readerFor(Class)方法都需要Class实例来生成对应的解析规则。
内容的提问来源于stack exchange,提问作者Paul Marcelin Bejan
相关产品推荐
相关产品推荐

