匿名内部类在 spring jdbctemplate 中常用于实现 rowmapper、preparedstatementsetter 等回调接口,以简化简单逻辑的代码;但 java 8+ 推荐优先使用 lambda 表达式替代,更简洁且避免类加载开销与可读性问题。

在 Spring 的 JdbcTemplate 中,匿名内部类最常用于实现回调接口(如 RowMapper、PreparedStatementSetter、ResultSetExtractor),以避免为简单逻辑单独定义命名类,提升代码简洁性。
用匿名内部类实现 RowMapper 映射单行结果
当查询返回单条记录且映射逻辑简单时,可直接在 queryForObject 或 query 中传入匿名 RowMapper:
User user = jdbcTemplate.queryForObject(
"SELECT id, name, email FROM users WHERE id = ?",
new Object[]{1L},
new RowMapper<user>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User u = new User();
u.setId(rs.getLong("id"));
u.setName(rs.getString("name"));
u.setEmail(rs.getString("email"));
return u;
}
}
);</user>
说明:每次从 ResultSet 取一行数据时,mapRow 被调用一次;注意字段名大小写需与数据库一致(或改用索引如 rs.getString(2))。
在 update 操作中用匿名 PreparedStatementSetter 绑定参数
执行带参数的更新语句时,可用匿名 PreparedStatementSetter 设置占位符值:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
jdbcTemplate.update(
"INSERT INTO users (name, email) VALUES (?, ?)",
new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, "Alice");
ps.setString(2, "alice@example.com");
}
}
);
说明:该方式适合参数少、逻辑不复用的场景;若参数来自变量,需确保变量是 final 或“事实上不可变”(Java 8+ 支持有效 final)。
替代方案:优先考虑 Lambda 表达式(Java 8+)
Spring 4.3+ 的 JdbcTemplate 回调接口基本都是函数式接口(含 @FunctionalInterface),推荐用 Lambda 替代匿名内部类,更简洁:
-
RowMapper→(rs, rowNum) -> { ... } -
PreparedStatementSetter→ps -> { ps.setString(1, "Bob"); } -
ResultSetExtractor→rs -> { ... }
例如:
User user = jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id = ?",
new Object[]{2L},
(rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name"), rs.getString("email"))
);
注意事项与边界情况
匿名内部类仍属于类加载范畴,会生成独立的 .class 文件(如 MyService$1.class);在 Spring 管理的 Bean 中使用时需注意:
- 不能直接访问非 final 的局部变量(编译报错)
- 若需访问外部对象的属性,建议通过方法参数传入,而非捕获复杂引用
- 逻辑较重或复用频繁时,应提取为命名类或静态工具方法,避免匿名类膨胀
- 调试时堆栈中显示为类似
MyDao$2.mapRow,可读性略低于 Lambda 或命名类
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










