发现一个有趣的现象 最近在学Spring封装好的jdbc时
public List<Emp> findAll(){
List<Emp> emps=null;
//query返回一个List<T> 但是内部却返回 public <T> T query(@NotNull String sql,
// @NotNull ResultSetExtractor<T> rse)
//throws DataAccessException
//T会自动转换为List<Emp>
emps=template.query("select * from emp",new EmpRowMapper());
return emps;
}
class EmpRowMapper implements RowMapper<Emp> {
//参数一结果集
//参数二 下标 对应结果集的下标 从0开始
@Override
public Emp mapRow(ResultSet rs, int rowNum) throws SQLException {
Emp emp=new Emp();
emp.setId(rs.getInt("id"));
emp.setName(rs.getString("name"));
emp.setAge(rs.getInt("age"));
return emp;
}
}
//以下是返回类型为List<T>的 query 方法的声明
1) public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException {
return query(sql, new RowMapperResultSetExtractor<T>(rowMapper));
}
//以下是内部调用的方法
2) public <T> T query(final String sql, final ResultSetExtractor<T> rse) throws DataAccessException {
// ....
return execute(new QueryStatementCallback());
}
为什么T可以返回给List<T>???
方法1)中的 T是Emp类型(怎么验证 可以使用 IDEA的Debug 在断点中插入测试代码) 所以方法2中的泛型也是Emp类型
//查看实现接口的泛型
Class targetClass = (Class)((ParameterizedType)rowMapper.getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0]; System.out.println(targetClass);
原因出在这里
public class RowMapperResultSetExtractor<T> implements ResultSetExtractor<List<T>> {
private final RowMapper<T> rowMapper;
private final int rowsExpected;
....
//程序最终会执行到这里
//此时T的类型依旧是Emp 但方法返回的T已经悄悄改变为List<T>
@Override
public List<T> extractData(ResultSet rs) throws SQLException {
List<T> results = (this.rowsExpected > 0 ? new ArrayList<T>(this.rowsExpected) : new ArrayList<T>());
int rowNum = 0;
while (rs.next()) {
results.add(this.rowMapper.mapRow(rs, rowNum++));
}
return results;
}
}
以下是该方法的主要调用栈
extractData:90, RowMapperResultSetExtractor (org.springframework.jdbc.core)
extractData:60, RowMapperResultSetExtractor (org.springframework.jdbc.core)
doInStatement:463, JdbcTemplate$1QueryStatementCallback (org.springframework.jdbc.core)
execute:408, JdbcTemplate (org.springframework.jdbc.core)
query:474, JdbcTemplate (org.springframework.jdbc.core)
query:484, JdbcTemplate (org.springframework.jdbc.core)
findAll:31, EmpDao (DAO)
testQuery:37, Demo (Test)