Java反射机制实战(搭配泛型使用)
Java反射是java高级特性里极其重要的一种。但是很多同学在刚接触的时候一定会想:这玩意这么麻烦,我用它干嘛?直接new 一个对象出来不好吗?
包括笔者在学习的时候也只知道有这么个东西,听老师说很多框架的底层用到的都是反射。仅此而已。
直到最近,笔者在项目重构中第一次使用到了反射+泛型。为此对反射也有了一点点浅薄的理解。也是感受到了其功能的强大。
项目背景如下:某电商项目,用户获取商品信息时,可以从多个维度上作为起点,比如常规的搜索功能,还有根据获取商品榜单,获取某个分类下的所有商品等等。
那么就以获取商品榜单为例:
通常在数据库中会存在以下几张表
- 榜单表,记录了榜单id,榜单名称,榜单的生效时间与过期时间等等。
- 商品表,记录了商品id,商品名称,商品预览图,商品链接等等,
- 榜单-商品关系表,记录了榜单与商品的关系。通常是一个榜单下有多个商品。也就是1-n。
但是工作以后遇到的业务可不止这么几张表,通常还要查店铺表获取店铺名字,查价格表获取商品的价格,查促销表获取促销/打折信息,评论表获取商品的所有评论等等等等,最后再拼接全部数据。
【Java反射机制实战(搭配泛型使用)】以上加粗的业务,在根据榜单查询商品时要走一遍,根据分类查询商品也要走一遍,根据搜索查询商品也要走一遍,查询单个商品时也要走一遍。
我原来的逻辑是:以查询单个商品作为底层方法,实现好该逻辑后。再在其他维度查询商品时,获得商品id的集合后,再遍历调用查询单个商品的方法。
该逻辑好处只有一个:复用了代码且写起来方便。但是坏处有很多很多:耦合度太高,缓存不好设置,扩展性太差等等。
所以在一个新需求来之后,我发现我的逻辑不足以支撑新需求的开发。于是重构了项目。
在重构项目时,用到了反射+泛型的方法抽取了加粗部分的代码作为公共代码。
在拿到有着商品id的List后,由于每种维度的list里的类型都不一样(榜单id+其他,分类id+其他),但是它们肯定有一个共同的字段productId,怎么抽取成公共类呢?答案是使用泛型,然后用反射得到productId
GetProductResponse getProductResponse(List ob, GetProductRequest getProductRequest, StringBuilder redisKey) throws NoSuchFieldException, IllegalAccessException {
//根据商品id查询商品的基本信息
List toDoList = new ArrayList<>();
for (T e : ob) {
Field t = e.getClass().getDeclaredField("productId");
t.setAccessible(true);
String productId = (String) t.get(e);
toDoList.addAll(getProductList(productId, getProductRequest));
}
//其他需要做的事,如找其他的字段,筛选,排序等
xxxxxxxx
return new GetProductResponse;
}
这里的重点是
- 使用泛型时,要在方法的最前面加上
,告诉jvm这是个泛型标识,不然不会识别List 。 - 使用getClass()方法获取到对应的类对象,再通过getDeclardFiled拿到对应的字段。
- 注意字段filed调用setAccessible(true)方法。如果没有这行代码,private的字段在调用filed.get(T)时会报错。
使代码可读性,可维护性变强,最重要的是架构清晰,解耦合,且行数加起来一下子少了几百行。
所以什么时候适合用反射呢?该怎么用呢?笔者在这里记录一种场景,也欢迎大家补充其他场景。
- 有多个维度或者说入口,他们的目的是一样的(根据榜单,分类等查询,目的都是为了获取商品信息)
- 在经过处理后,它们具有共同的字段,且这个字段是后续步骤的关键(榜单,分类里都存了productId的list,但是于此同时,除了productId,它们的其余字段是不一样的,比如榜单id,分类id)
- 搭配泛型一起使用,泛型的作用是使这个方法能成为多个维度的共同底层,而反射是为了获取泛型里的重要的字段(productId)
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 事件代理
- Java|Java OpenCV图像处理之SIFT角点检测详解
- java中如何实现重建二叉树
- 数组常用方法一
- 【Hadoop踩雷】Mac下安装Hadoop3以及Java版本问题
- Java|Java基础——数组
- RxJava|RxJava 在Android项目中的使用(一)
- java之static、static|java之static、static final、final的区别与应用
- 深入理解|深入理解 Android 9.0 Crash 机制(二)