[14-03] 示例:利用匿名内部类简化代码

内部类的其中一个优势就是可以简化代码,现在以一个常用的JDBC获取数据封装对象的例子,来简单谈谈如何使用匿名内部类来简化代码。

下面这段代码,是用JDBC连接,到数据库查询到数据之后,将数据封装到对象中进行返回,很常见的场景:

  1. public List<DepartmentMember> getMemberByDepartmentId(long departmentId) {
  2. List<DepartmentMember> memberList = new ArrayList<DepartmentMember>();
  3. Connection conn = null;
  4. PreparedStatement ps = null;
  5. ResultSet rs = null;
  6. String sql = "SELECT m.id,m.name,m.phone,d.value " +
  7. "FROM t_department_member m LEFT JOIN p_dictionary d ON m.job_id = d.id WHERE m.department_id=?";
  8. try {
  9. conn = DBUtil.getConnection();
  10. ps = conn.prepareStatement(sql);
  11. ps.setLong(1, departmentId);
  12. rs = ps.executeQuery();
  13. while (rs.next()) {
  14. DepartmentMember member = new DepartmentMember();
  15. member.setId(rs.getLong("id"));
  16. member.setName(rs.getString("name"));
  17. member.setPhone(rs.getString("phone"));
  18. member.setJob_name(rs.getString("value"));
  19. memberList.add(member);
  20. }
  21. } catch (SQLException e) {
  22. e.printStackTrace();
  23. } finally {
  24. DBUtil.closeConnection(conn, ps, rs);
  25. }
  26. return memberList;
  27. }

可以看到,使用JDBC连接获取数据的话,重复的代码很多(如上图黄色标注的部分),数据连接,获取语句对象,执行查询操作,抓取异常处理,以及关闭连接。这部分代码完全没必要每次都写,想想看,每写一次类似的获取数据的方法,这些代码要copy一次,也是很麻烦的了。

设想一下,我能不能写一个方法,把这些重复的代码写好,每次只需要传入需要变动的那部分就行了。那么问题来了,变动的部分,如果只是sql,那还行,毕竟是String字符串,可以作为形参传入;那我 while(rs.next()) 中的执行代码也想传入,怎么办?Java是不像JS那种可以把函数作为参数的,只能是对象。

没关系,我们先按这个思路试一下,把重复的代码单独写在一个方法中:

  • 为了能让支持其他数据库连接,我们把连接对象作为方法参数传入
  • 为了传入变动代码,我们需要设定一个抽象类作为参数,在方法中执行其方法
  1. public void executeQuery(Connection conn, String sql, SqlExecute action) {
  2. long start = System.currentTimeMillis();
  3. log.debug("execute query start, sql:");
  4. log.debug(sql);
  5. PreparedStatement ps = null;
  6. ResultSet rs = null;
  7. try {
  8. ps = conn.prepareStatement(sql);
  9. //set prepared sql params
  10. action.setParam(ps);
  11. rs = ps.executeQuery();
  12. while (rs.next()) {
  13. //do things while resultset.next()
  14. action.next(rs);
  15. }
  16. } catch (SQLException e) {
  17. e.printStackTrace();
  18. } finally {
  19. DBUtil.closeConnection(conn, ps, rs);
  20. }
  21. long end = System.currentTimeMillis();
  22. log.debug("execute query end, cost time:" + (end - start) + "ms");
  23. }
  1. public abstract class SqlExecute {
  2. /**
  3. * 预编译语句对象赋值
  4. *
  5. * @param ps PreparedStatement预编译语句对象
  6. */
  7. void setParam(PreparedStatement ps) throws SQLException {
  8. //for override
  9. }
  10. /**
  11. * 执行操作
  12. *
  13. * @param rs ResultSet结果集
  14. */
  15. void next(ResultSet rs) throws SQLException {
  16. //for override
  17. }
  18. }

可以看到,由此以来,我只需要调用 executeQuery(Connection conn, String sql, SqlExecute action) 方法,然后需要执行的操作,以SqlExecute的实现类来传入就可以了。但是,每次都为了一个方法,新建一个类来实现SqlExecute,反而显得更繁琐了。幸好,我们有匿名内部类,实际上,我们使用的时候,会变成这样。还是以文章前面的JDBC连接为示例:

  1. public List<DepartmentMember> getMemberByDepartmentId(final long departmentId) {
  2. final List<DepartmentMember> memberList = new ArrayList<DepartmentMember>();
  3. String sql = "SELECT m.id,m.name,m.phone,d.value " +
  4. "FROM t_department_member m LEFT JOIN p_dictionary d ON m.job_id = d.id WHERE m.department_id=?";
  5. executeQuery(DBUtil.getConnection(), sql, new SqlExecute() {
  6. @Override
  7. void setParam(PreparedStatement ps) throws SQLException {
  8. ps.setLong(1, departmentId);
  9. }
  10. @Override
  11. void next(ResultSet rs) throws SQLException {
  12. DepartmentMember member = new DepartmentMember();
  13. member.setId(rs.getLong("id"));
  14. member.setName(rs.getString("name"));
  15. member.setPhone(rs.getString("phone"));
  16. member.setJob_name(rs.getString("value"));
  17. memberList.add(member);
  18. }
  19. });
  20. return memberList;
  21. }

如上方式可以看到,相当于直接把变动的代码作为了参数传入方法。而好处在于,代码变得简洁直观,setParam() 部分就是设置预编译语句对象的值,而next() 就是在对结果集每一行要执行的操作,一目了然,如果后续需要代码变动,在哪里改就可以迅速找到,同时也不需要在此处去特别使用try catch包括代码和处理异常。另外,在executeQuery方法中,顺便还加入了日志打印的方法,因此你也不必再单独每个方法去写一些日志输出的方法了。

最后,值得一提的是,因为内部类的原理,所以这里可以看到,传参的基本数据类型(如departmentId),以及非内部类中的引用数据类型(对象,如memberList),都必须标注为final修饰,这个在内部类的基础知识点钟已经提到,这里就不再过多阐述了。

原文地址:https://www.cnblogs.com/deng-cc/p/8320375.html

时间: 2024-10-06 00:53:26

[14-03] 示例:利用匿名内部类简化代码的相关文章

JS当中利用&amp;&amp;和||简化代码

var add_level = 0; if(add_step == 5){ add_level = 1; } else if(add_step == 10){ add_level = 2; } else if(add_step == 12){ add_level = 3; } else if(add_step == 15){ add_level = 4; } else { add_level = 0; } var add_level = 0; switch(add_step){ case 5 :

异步编程系列第03章 自己写异步代码

p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提高下英文,用我拙劣的英文翻译一些重要的部分,纯属娱乐,简单分享,保持学习,谨记谦虚. 如果你觉得这件事儿没意义翻译的又差,尽情的踩吧.如果你觉得值得鼓励,感谢留下你的赞,愿爱技术的园友们在今后每一次应该猛烈突破的时候,不选择知难而退.在每一次应该独立思考的时候,不选择随波逐流,应该全力以赴的时候,不选择尽力而

用block做事件回调来简化代码,提高开发效率

我们在自定义view的时候,通常要考虑view的封装复用,所以如何把view的事件回调给Controller就是个需要好好考虑的问题, 一般来说,可选的方式主要有target-action和delegate,以及这次要强烈推荐的block. target-action和delegate方式有个很不方便的地方,就是配置代码和action代码不在同一个地方,你肯定要多写一个selector方法或者delegate方法,这就带来一个问题,一旦代码比较长或者selector方法比较多,找起来就很不方便.

链表中用标兵结点简化代码

标兵结点(头结点)是在链表中的第一个结点,不存放数据,仅仅是个标记 利用标兵结点可以简化代码.下面实现双向链表中的按值删除元素的函数,分别实现 带标兵结点和不带标兵结点两版本,对比可见标兵结点的好处. 结点声明如下: struct Node { int value; Node *prev; Node *next; } int del_doublelist(Node*&h,int v)//不带标兵结点 { Node*p=h; while(p!=NULL&&p->value!=v

Android开发实践:利用ProGuard进行代码混淆

由于Android的代码大都是Java代码,所以挺容易被反编译的,好在Android ADT为我们集成了混淆代码的工具,一来可以混淆我们的代码,让程序被反编译后基本看不懂,另外还能起到代码优化的作用.发布项目前,建议打开Android的代码混淆功能. Android ADT主要通过ProGuard工具来提供代码混淆,网上也有挺多博客文章讲这个的,但感觉很多都介绍得太过于复杂,这里我就以问答的方式来更加简洁地介绍下ProGuard吧. 1. ProGuard是什么 ProGuard是一个工具,用来

.NET技术-1.0.使用反射、特性简化代码(验证Model类)

使用反射.特性简化代码 参考项目:利用反射验证Model类/AssemblyVerification 假设现在有一个学生类(Student) /// <summary> /// 学生类 /// </summary> public class Student { /// <summary> /// 名字 /// </summary> private string name; public string Name { get { return name; } s

【Butter Knife】依赖注入方式简化代码提高开发效率

Butter Knife是一款非常不错的开源框架,其目的是简化代码,提高项目的开发效率. 以往的开发我们经常需要用findViewById(R.xx.xxx);几乎没个页面都会涉及到,无论Activity还是Fragment甚至listView.GridView中的 Adapter.这些重复性的代码会让人觉得很枯燥,因为闭上眼都不会敲错的代码,每天重复几百遍是有点耗时,尽管有代码提示.而且可能会因为不同field的忘记书写而导致NullPoint空指针. 那么还是直接进入主题: 步骤: 第三方框

Java简化代码神器-Lombok

一.背景 前段时间在开源社区中发现了一个比较牛逼的简化Java代码的神器-Lombok,接着自己写了demo进行测试和练习,感觉真的很不错,特此分享给需要的小伙伴们~ 二.开发之前的准备 1.lombok的官方网站:http://projectlombok.org/ 2.lombok IDE插件安装 要想在IDE中使用lombok是需要安装相关插件的.如果不安装,IDE 则无法解析 lombok 注解.安装之前需要首先在官方网站下载相关jar包,现在官网版本是:1.16.8. [1].使用jav

2-5 利用RestTemplateCore简化调用Consul中的服务

1.必须要安装RestTemplateCore包 2.请求服务,必须要知道 a Consul服务器的地址:b 请求的服务名 ;c 具体请求的api接口 利用RestTemplateCore简化调用Consul中的服务代码如下: 原文地址:https://www.cnblogs.com/wholeworld/p/9291090.html