使用java泛型设计通用方法
泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 因此我们可以利用泛型和反射来设计一些通用方法. 现在有2张表, 一张user表和一张student表.
user:
student:
如果要根据id查询数据, 你会怎么做呢?写2个方法分别查询user和student?其实这时候我们就可以使用泛型和反射写一个通用的方法.
user的实体类:
private Integer id;
private String username;
private String password;
private String hobby;
//getXxx方法和setXxx方法
student实体类:
private Integer id;
private String name;
private Integer age;
//getXxx方法和setXxx方法
BaseDao接口:
public interface BaseDao<T> {
//根据id查询的方法
T findById(Integer id);
}
BaseDaoImpl类, 实现了BaseDao接口, 通用方法就在这里面完成:
//设置为抽象的, 不让他实例化, 让其子类实例化就行了
//通过泛型设计通用方法的关键就是利用反射拿到泛型的具体类型
public abstract class BaseDaoImpl<T> implements BaseDao<T> {
private String tableName; //表名
private Class<T> actualType;//真实类型 /**
* findById(Integer id)这个方法被子类继承了, 假设我们在UserDaoImpl中操作, 此时参数化类型T为User
* 下面的讲解都假设是在UserDaoImpl中进行的
*/
//把公共部分可以放到构造方法中
@SuppressWarnings("unchecked")
public BaseDaoImpl() {
//返回类型是Type 是 Java 编程语言中所有类型的公共高级接口. 它们包括原始类型、参数化类型、数组类型、类型变量和基本类型.
//Type的已知子接口: ParameterizedType 表示参数化类型, 如 Collection<String>.
//getClass()得到UserDaoImpl的Class, 得到Class一般有3中方式: getClass(), 类名.class, Class.forName()
Type type = getClass().getGenericSuperclass();//获取UserDaoImpl<User>的参数化类型的父类BaseDaoImpl<User>
//由于我们得到的是一个参数化类型, 所以转成ParameterizedType, 因为需要使用里面的方法
ParameterizedType pt = (ParameterizedType) type;//强转
Type[] actualTypeArr = pt.getActualTypeArguments();//获取真实参数类型数组[User.class], 可以调试看到这里的值
actualType = (Class<T>) actualTypeArr[0];//数组只有一个元素
tableName = actualType.getSimpleName();
} @Override
public T findById(Integer id) {
String sql = "select * from " + tableName + " where id = ?";
try {
return QRUtils.getQueryRunner().query(sql, new BeanHandler<T>(actualType), id);
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
连接数据库操作是用的c3p0和dbutils, 有关这方面的内容可以参看我以前的随笔.
UserDao接口, 继承BaseDao接口:
public interface UserDao<T> extends BaseDao<T> {
}
UserDaoImpl类, 实现UserDao接口, 继承BaseDaoImpl类, 可以看到里面什么方法也没有:
public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao<User> {
}
StudentDao接口, 继承BaseDao接口:
public interface StudentDao<T> extends BaseDao<T> {
}
StudentDaoImpl类, 实现StudentDao接口, 继承BaseDaoImpl类, 也可以看到里面什么方法也没有:
public class StudentDaoImpl extends BaseDaoImpl<Student> implements StudentDao<Student> {
}
从以上dao可以看到, 我是在继承BaseDaoImpl类时把泛型具体化了.
测试:
@Test
public void testGeneric() throws Exception {
UserDao<User> userDao = new UserDaoImpl();
System.out.println(userDao.findById(1)); System.out.println("-------------------");
StudentDao<Student> studentDao = new StudentDaoImpl();
System.out.println(studentDao.findById(1));
}
看一下测试的结果: 同一个方法把2张表中的数据都查出来了
有关泛型的基本使用, 请参考java泛型基础
使用java泛型设计通用方法的更多相关文章
- 初识Java泛型以及桥接方法
泛型的由来 在编写程序时,可能会有这样的需求:容器类,比如java中常见的list等.为了使容器可以保存多种类型的数据,需要编写多种容器类,每一个容器类中规定好了可以操作的数据类型.此时可能会有Int ...
- java导出excel通用方法
首先需要引入的jar包: 正式代码了. import java.io.FileOutputStream; import java.io.OutputStream; import java.net.UR ...
- Effective Java - [3. 对象通用方法]
Item 10. 若覆盖equals方法,需要遵守规则
- java泛型基础
泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 这种参数类型可以用在类.接口和方法的创建中, 分别称为泛型类.泛型接口.泛型方法. Ja ...
- java 泛型的类型擦除与桥方法
泛型类 --代码参考:java核心技术 卷1 第十版 public class Pair<T> { private T first; private T second; //构造器 pub ...
- Java泛型-内部原理: 类型擦除以及类型擦除带来的问题
一:Java泛型的实现方法:类型擦除 大家都知道,Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除.Java的泛型基本上都是在编译 ...
- java泛型 8 泛型的内部原理:类型擦除以及类型擦除带来的问题
参考:java核心技术 一.Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型.为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉.正确理解泛型概念的首 ...
- Java泛型学习笔记--Java泛型和C#泛型比较学习(一)
总结Java的泛型前,先简单的介绍下C#的泛型,通过对比,比较学习Java泛型的目的和设计意图.C#泛型是C#语言2.0和通用语言运行时(CLR)同时支持的一个特性(这一点是导致C#泛型和Java泛型 ...
- java泛型(二)、泛型的内部原理:类型擦除以及类型擦除带来的问题
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
随机推荐
- 使用Expression实现数据的任意字段过滤(1)
在项目常常要和数据表格打交道. 现在BS的通常做法都是前端用一个js的Grid控件, 然后通过ajax的方式从后台加载数据, 然后将数据和Grid绑定. 数据往往不是一页可以显示完的, 所以要加分页: ...
- 【干货分享】流程DEMO-资产请购单
流程名: 资产请购 业务描述: 流程发起时,会检查预算,如果预算不够,流程必须经过总裁审批,如果预算够用,将发起流程,同时占用相应金额的预算,但撤销流程会释放相应金额的预算. 流程相关文件: 流程 ...
- Android程序中--不能改变的事情
有时,开发人员会对应用程序进行更改,当安装为以前版本的更新时出现令人惊讶的结果 - 快捷方式断开,小部件消失或甚至根本无法安装. 应用程序的某些部分在发布后是不可变的,您可以通过理解它们来避免意外. ...
- 仿陌陌的ios客户端+服务端源码项目
软件功能:模仿陌陌客户端,功能很相似,注册.登陆.上传照片.浏览照片.浏览查找附近会员.关注.取消关注.聊天.语音和文字聊天,还有拼车和搭车的功能,支持微博分享和查找好友. 后台是php+mysql, ...
- 二叉树的创建和遍历(C版和java版)
以这颗树为例:#表示空节点前序遍历(根->左->右)为:ABD##E##C#F## 中序遍历(左->根->右)为:#D#B#E#A#C#F# 后序遍历(左->右-> ...
- 关于Java中进程和线程的详解
一.进程:是程序的一次动态执行,它对应着从代码加载,执行至执行完毕的一个完整的过程,是一个动态的实体,它有自己的生命 周期.它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而 ...
- [PHP源码阅读]empty和isset函数
近日被问到PHP中empty和isset函数时怎么判断变量的,刚开始我是一脸懵逼的,因为我自己也只是一知半解,为了弄懂其真正的原理,赶紧翻开源码研究研究.经过分析可发现两个函数调用的都是同一个函数,因 ...
- Cowboy 开源 WebSocket 网络库
Cowboy.WebSockets 是一个托管在 GitHub 上的基于 .NET/C# 实现的开源 WebSocket 网络库,其完整的实现了 RFC 6455 (The WebSocket Pro ...
- NodeJS的代码调试和性能调优
本文转自我的个人博客. NodeJS 自 2009 年显露人间,到现在已经六个年头了,由于各种原因,中间派生出了个兄弟,叫做 iojs,最近兄弟继续合体,衍生出了 nodejs4.0 版本,这东西算是 ...
- Google Java编程库Guava介绍
本系列想介绍下Java下开源的优秀编程库--Guava[ˈgwɑːvə].它包含了Google在Java项目中使用一些核心库,包含集合(Collections),缓存(Caching),并发编程库(C ...