如何实现泛型接口的方法?附相关泛型接口与方法代码示例
首先得指出你定义的ParsableDTO<T>接口里有个小问题——方法级的泛型<T>和接口的泛型参数重名了,这会导致接口的泛型被方法的泛型覆盖,完全失去了泛型接口的意义。咱们先把接口修正过来,再看具体的实现方式。
1. 修正泛型接口
把方法上的<T>去掉,让方法返回的类型就是接口定义的泛型参数T,这样才能和后续的泛型约束匹配:
public interface ParsableDTO<T> { T parse(ResultSet rs) throws SQLException; }
2. 实现具体的DTO类
接下来以一个实际的DTO为例,比如UserDTO,实现修正后的ParsableDTO<UserDTO>,在parse方法里从ResultSet中读取数据库字段值,组装成当前DTO实例:
public class UserDTO implements ParsableDTO<UserDTO> { private Long id; private String username; private String email; // 无参构造器、Getter/Setter方法省略 @Override public UserDTO parse(ResultSet rs) throws SQLException { UserDTO user = new UserDTO(); user.setId(rs.getLong("id")); user.setUsername(rs.getString("username")); user.setEmail(rs.getString("email")); return user; } }
这里的核心是:实现类要明确指定接口的泛型参数为自身类型(也就是F-bounded泛型,和你getParsableDTOs方法里的T extends ParsableDTO<T>约束对应),这样parse方法就能返回当前DTO的实例,保证类型安全。
3. 完善getParsableDTOs方法的循环逻辑
在你的getParsableDTOs方法的while(rs.next())循环里,需要通过传入的dto_class创建DTO实例,然后调用其parse方法填充数据:
public <T extends ParsableDTO<T>> List<T> getParsableDTOs(String table, Class<T> dto_class) { List<T> rtn_lst = new ArrayList<T>(); ResultSet rs = doQueryWithReturn(StringQueryComposer.createLikeSelectQuery(table, null, null, null, true)); try { // 获取DTO的无参构造器(如果DTO用有参构造,需调整参数类型匹配) Constructor<T> constructor = dto_class.getConstructor(); while(rs.next()) { T dto = constructor.newInstance(); // 调用parse方法从ResultSet中读取数据并填充DTO T parsedDto = dto.parse(rs); rtn_lst.add(parsedDto); } } catch (SQLException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { // 这里可以根据业务需求处理异常,比如打印日志或抛出自定义异常 e.printStackTrace(); } finally { // 务必记得关闭ResultSet等数据库资源,避免泄漏 try { if(rs != null) rs.close(); } catch (SQLException e) { e.printStackTrace(); } } return rtn_lst; }
注意:Java 9之后
Class.newInstance()已被标记为过时,推荐用Constructor.newInstance()来创建实例,这样能更清晰地处理构造器相关的异常。如果你的DTO没有无参构造器,需要调整构造器的获取逻辑,传入对应的参数类型即可。
额外说明
为什么要修正接口的泛型?原来的方法里的<T>是方法自身的泛型参数,和接口的<T>完全是两个独立的类型,编译器无法保证你返回的T就是实现接口的DTO类型,会导致getParsableDTOs方法的泛型约束失效,甚至运行时出现类型转换异常。修正后,接口的泛型和方法返回类型绑定,就能全程保证类型安全。
内容的提问来源于stack exchange,提问作者user4789408

