java 泛型 与类反射_Java技能 —— 对象泛型以及类反射机制的应用

一,泛型和反射的初识

Java泛型是JDK 5中引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制允许程序员在编译时监测非法的类型。简单的理解就是参数化类型,我们一开始就知道这个泛型T是String,Student,还是其他,而不是Object。如此对我们编码比较友好,以及类型安全问题也得到解决。

Java反射是Java的一个重要的高级特性,很多重复性的工作都可以利用这个特性进行系统底层的编写。简单的理解,任何一个类都可以利用这个机制获取到类,方法,属性等。即使是泛型也能进行获取到类型。

基于上述说明,对这两个点进行例子+说明的方式进行编写文章。

二,泛型

自JDK5以来,我们其实或多或少已经使用到泛型的东西,如列表

List list = new ArrayList();

Map map = HashMap();

这些都是泛型的应用。

首个示例:(数据库增删改查示例)

先定义一个基础的数据库对象都会包括字段的类:

import lombok.Data;

import java.util.Date;

@Data

public class BaseModel {

private Long id;

private Date createdAt;

private String createUserId;

private String createUserName;

private Date updatedAt;

private String updateUserId;

private String updateUserName;

}

再写数据库操作基础接口类:

import java.io.Serializable;

import java.util.List;

/*** 基础 DAO接口** @author Lawliet*/

public interface BaseMapper {

/*** 保存,存在id就更新,不存在就添加** @param entity 实体对象* @return boolean*/

int save(T entity);

/***

* 插入一条记录(选择字段,策略插入)*

** @param entity 实体对象* @return boolean*/

int insert(T entity);

/***

* 插入一条记录(全部字段)*

** @param entity 实体对象* @return boolean*/

int insertAllColumn(T entity);

/*** 插入(批量)** @param entityList 实体对象列表* @return boolean*/

int insertBatch(List entityList);

/*** 根据 ID 删除** @param id 主键ID* @return boolean*/

int deleteById(Serializable id);

/*** 删除(根据ID 批量删除)** @param idList 主键ID列表* @return boolean*/

int deleteBatchIds(List idList);

/*** 根据 ID 选择修改** @param entity 实体对象* @return boolean*/

int updateById(T entity);

/*** 根据ID 批量更新** @param entityList 实体对象列表* @return boolean*/

int updateBatchById(List entityList);

/*** 根据 ID 查询** @param id 主键ID* @return V*/

T selectById(Serializable id);

/*** 查询(根据ID 批量查询)** @param idList 主键ID列表* @return List*/

List selectBatchIds(List idList);

}

再写上述接口的实现,由于只是例子,所以只是简单打印消息:

import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;

import java.util.List;

/*** 基础 DAO** @author Lawliet*/

@Slf4j

public class BaseManager implements BaseMapper {

@Override

public int save(T entity) {

System.out.println("底层获取到数据:" + entity.toString());

System.out.println("获取到model[ID]属性: " + entity.getId());

return 0;

}

@Override

public int insert(T entity) {

System.out.println("底层获取到数据:" + entity.toString());

System.out.println("获取到model属性" + entity.getId());

return 0;

}

@Override

public int insertAllColumn(T entity) {

System.out.println("底层获取到数据:" + entity.toString());

System.out.println("获取到model属性" + entity.getId());

return 0;

}

@Override

public int insertBatch(List entityList) {

System.out.println("底层获取到数据:" + entityList.toString());

System.out.println("获取到model属性" + entityList.get(0).getId());

return 0;

}

@Override

public int deleteById(Serializable id) {

System.out.println("获取到model属性" + id);

return 0;

}

@Override

public int deleteBatchIds(List idList) {

return 0;

}

@Override

public int updateById(T entity) {

return 0;

}

@Override

public int updateBatchById(List entityList) {

return 0;

}

@Override

public T selectById(Serializable id) {

return null;

}

@Override

public List selectBatchIds(List idList) {

return null;

}

}

上述写完之后,则底层增删改查的底层算是完成,则需要写业务的类:(以用户User为例)

import lombok.Data;

import lombok.ToString;

@Data

@ToString(callSuper = true)

public class User extends BaseModel{

private String userName;

private String userTitle;

private Integer userAge;

private Integer userSex;

}

public class UserManager extends BaseManager{

}

由于该例子是没使用springboot,所以实际运用会加上@Service的注解的。

上最后的测试代码:

public class Test {

public static void main(String[] args) {

//创建用户,实际应用场景应该由前端传数据过来 User user = new User();

user.setUserAge(11);

user.setUserName("小明");

user.setUserSex(1);

user.setUserTitle("学生");

user.setId(12138L);

//调用方法 UserManager userManager = new UserManager();

userManager.save(user);

}

}

效果如下:

通过上述简单的示例,我们可以体验到泛型的魅力,就是我只需要写好最底层的基础类:BaseMapper 和 BaseManager,后面我们只需要写很简单的继承,即可实现数据库的增删改查的事情,效率提升N倍。

上述示例不想敲代码的,可以下载体验学习:

第二个泛型实例:(应用于实际场景,easypoi实现文件导入导出)

由于篇幅有点过长,因此展示导出的实例,会贴上云盘下载地址。

定义导出接口:

import java.io.Serializable;

import java.util.List;

import java.util.Map;

/*** 导出监听器* 创建时间 2019-12-30 11:28** @author lincf2*/

public abstract class BaseExportDataPoiListener implements Serializable {

/*** 导出附件名称*/

protected abstract String getFileName();

/*** 导出数据*/

protected abstract List getExportData(Map map);

}

实现上述接口的静态controller代码,基本上全部导出逻辑在这个位置

import com.alibaba.excel.EasyExcel;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.io.Serializable;

import java.lang.reflect.ParameterizedType;

import java.net.URLEncoder;

import java.util.*;

/*** 基础导出模板* 创建时间 2019-12-30 11:13** @author lincf2*/

public abstract class BaseExportDataPoiController implements Serializable {

private static Logger logger = LoggerFactory.getLogger(BaseExportDataPoiController.class);

@RequestMapping(value = "/excel/export", method = {RequestMethod.GET})

public void exportExcel(HttpServletRequest request, HttpServletResponse response) throws IOException {

L l = this.getExportDataPoiListener();

response.setContentType("application/vnd.ms-excel");

response.setCharacterEncoding("utf-8");

String fileName = l.getFileName() + ".xlsx";

fileName = URLEncoder.encode(fileName, "UTF-8");

response.setHeader("Content-disposition", "attachment;filename=" + fileName);

List dataList = l.getExportData(this.getQuery(request));

EasyExcel.write(response.getOutputStream(), this.getTClass()).sheet("sheet").doWrite(dataList);

}

private Class getTClass() {

Class tClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

return tClass;

}

private L getExportDataPoiListener() {

ParameterizedType ptype = (ParameterizedType) this.getClass().getGenericSuperclass();

Class clazz = (Class) ptype.getActualTypeArguments()[1];

try {

L l = (L) clazz.newInstance();

return l;

} catch (Exception exp) {

logger.error("无法初始化导出对象L : {}", exp.getMessage());

}

return null;

}

private Map getQuery(HttpServletRequest request) {

Map map = new HashMap();

Enumeration paramNames = request.getParameterNames();

while (paramNames.hasMoreElements()) {

String paramName = (String) paramNames.nextElement();

String[] paramValues = request.getParameterValues(paramName);

if (paramValues.length > 0) {

String paramValue = paramValues[0];

if (paramValue.length() != 0) {

map.put(paramName, paramValue);

}

}

}

Set> set = map.entrySet();

for (Map.Entry entry : set) {

logger.debug(entry.getKey() + ":" + entry.getValue());

}

return map;

}

}

根据上述底层编写业务实现:(以账户为例)

导出对象:

import com.alibaba.excel.annotation.ExcelProperty;

import com.alibaba.excel.annotation.write.style.ColumnWidth;

import com.alibaba.excel.annotation.write.style.ContentRowHeight;

import com.alibaba.excel.annotation.write.style.HeadRowHeight;

import lombok.Data;

import lombok.ToString;

import java.io.Serializable;

import java.math.BigDecimal;

import java.util.Date;

/*** 类描述* 创建时间 2019-12-30 14:55** @author lincf2*/

@Data

@ToString(callSuper = true)

@ContentRowHeight(20)//高度@HeadRowHeight(20)

@ColumnWidth(25)//宽度public class DemoExportVo implements Serializable {

/*** 总金额*/

@ExcelProperty(value = "总金额", index = 0)

private BigDecimal amount;

/*** 基本余额*/

@ExcelProperty(value = "基本余额", index = 1)

private BigDecimal balance;

/*** 赠送金额*/

@ExcelProperty(value = "赠送金额", index = 2)

private BigDecimal largessAmount;

/*** 冻结金额*/

@ExcelProperty(value = "冻结金额", index = 3)

private BigDecimal freezeAmount;

/*** md5加密保存*/

@ExcelProperty(value = "密码", index = 4)

private String payPasswd;

/*** 商家名称*/

@ExcelProperty(value = "商家名称", index = 5)

private String objectName;

/*** 有效期*/

@ExcelProperty(value = "有效期", index = 6)

private Date expireDate;

}

实现导出业务逻辑,返回数据的监听器层

import com.lawliet.demo.base.BaseExportDataPoiListener;

import lombok.Data;

import lombok.ToString;

import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

import java.util.Map;

/*** 类描述* 创建时间 2019-12-30 14:59** @author lincf2*/

@Slf4j

@Data

@ToString(callSuper = true)

public class DemoExportDataPoiListener extends BaseExportDataPoiListener {

@Override

protected String getFileName() {

return "导出demo文件";

}

@Override

protected List getExportData(Map map) {

log.info("信息参数:" + map.toString());

//TODO 根据上面参数处理业务,做成如下数据即可

List demoExportVoList = new ArrayList();

DemoExportVo demoExportVo = new DemoExportVo();

demoExportVo.setAmount(new BigDecimal("100"));

demoExportVo.setBalance(new BigDecimal("100"));

demoExportVo.setExpireDate(new Date());

demoExportVo.setFreezeAmount(new BigDecimal("100"));

demoExportVo.setObjectName("周小系");

demoExportVo.setPayPasswd("sisdjahhgdjdhdfhvvhjsjsj");

demoExportVoList.add(demoExportVo);

return demoExportVoList;

}

}

最后的controller写法

import com.lawliet.demo.base.BaseExportDataPoiController;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

/*** 类描述* 创建时间 2019-12-30 14:51** @author lincf2** http://127.0.0.1:8081/demo/alibaba/account/excel/export?id=12&name=Lawliet**/

@Controller

@RequestMapping("/demo/alibaba/account")

public class DemoExportDataPoiController extends BaseExportDataPoiController {

}

最后复制上面链接去浏览器打开就可以导出数据,效果图如下:

总结:编写该底层也是为了让我们更加注重业务的开发,编写我们导出的VO,导出名称,导出的业务数据来源。统一controller写法。简易的编写几个业务类,即可实现高性能的导出功能。也是泛型给我们带来的魅力。学好泛型等于让自己效率提高一个档次,代码质量也会上去。

下面链接是整个demo项目,包括导出导入功能实现,在生产环境验证过的。

三,反射

下次更新....

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值