写点什么

《对线面试官》Java 泛型

作者:Java3y
  • 2022 年 5 月 07 日
  • 本文字数:1631 字

    阅读完需:约 5 分钟

《对线面试官》Java泛型

面试官:这次咱们就来聊聊泛型呗?你对泛型有多少了解?

候选者:在 Java 中的泛型简单来说就是:在创建对象或调用方法的时候才明确下具体的类型

候选者:使用泛型的好处就是代码更加简洁(不再需要强制转换),程序更加健壮(在编译期间没有警告,在运行期就不会出现 ClassCastException 异常)

面试官:平时在工作中用得多吗?

候选者:在操作集合的时候,还是很多的,毕竟方便啊。

List<String> lists = new ArrayList<>();lists.add("对线面试官");
复制代码

候选者:如果是其他场景的话,那就是在写「基础组件」的时候了。

面试官:来,说说背景吧,你是怎么写的。

候选者:再明确一下泛型就是「在创建对象或调用方法的时候才明确下具体的类型」,而组件为了做到足够的通用性,是不知道「用户」传入什么类型参数进来的,所以在这种情况下用泛型就是很好的实践。

候选者:这块可以参考SpringData JPA 的JpaRepository写法。

public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort sort);
List<T> findAllById(Iterable<ID> ids);
<S extends T> List<S> saveAll(Iterable<S> entities);
void flush();
<S extends T> S saveAndFlush(S entity);
void deleteInBatch(Iterable<T> entities);
void deleteAllInBatch();
T getOne(ID id);
@Override <S extends T> List<S> findAll(Example<S> example);
@Override <S extends T> List<S> findAll(Example<S> example, Sort sort);}
复制代码

候选者:要写组件,还是离不开 Java 反射机制(能够从运行时获取信息),所以一般组件是泛型+反射来实现的。

候选者:回到我所讲的组件吧,背景是这样的:我这边有个需求,需要根据某些字段进行聚合。

候选者:换到 SQL 其实就是select sum(column1),sum(column2) from table group by field1,field2

候选者:需要 sum 和 group by 的列肯定是由业务方自己传入,而 SQL 的表 其实就是我们的 POJO(传入的字段也肯定是 POJO 的属性)

候选者:单个业务实际可以在参数上写死 POJO,但为了做得更加通用,我把入参设置为泛型

候选者:拿到参数后,通过反射获取其字段具体的值,做累加就好了。

// 传入 需要group by 和 sum 的字段名public cacheMap(List<String> groupByKeys, List<String> sumValues) {  this.groupByKeys = groupByKeys;  this.sumValues = sumValues;}
private void excute(T e) { // 从pojo 取出需要group by 的字段 list List<Object> key = buildPrimaryKey(e); // primaryMap 是存储结果的Map T value = primaryMap.get(key); // 如果从存储结果找到有相应记录 if (value != null) { for (String elem : sumValues) { // 反射获取对应的字段,做累加处理 Field field = getDeclaredField(elem, e); if (field.get(e) instanceof Integer) { field.set(value, (Integer) field.get(e) + (Integer) field.get(value)); } else if (field.get(e) instanceof Long) { field.set(value, (Long) field.get(e) + (Long) field.get(value)); } else { throw new RuntimeException("类型异常,请处理异常"); } } // 处理时间记录 Field field = getDeclaredField("updated", value); if (null != field) { field.set(value, DateTimeUtils.getCurrentTime()); } } else { // group by 字段 第一次进来 try { primaryMap.put(key, Tclone(e)); createdMap.put(key, DateTimeUtils.getCurrentTime()); }catch (Exception ex) { log.info("first put value error {}" , e); } }}
复制代码

候选者:理解了泛型的作用之后,再去审视自己代码时,就可以判断是否需要用到泛型了。

面试官:嗯,可以的,总体来看有自己的见解。



发布于: 刚刚阅读数: 4
用户头像

Java3y

关注

贪财好色,有所为,有所不为 2018.11.08 加入

《对线面试官》系列在公众号「Java3y」有图文版、电子书版、纯文版,欢迎批判

评论 (1 条评论)

发布
用户头像
对线面试官系列正在连载中...
刚刚
回复
没有更多了
《对线面试官》Java泛型_Java_Java3y_InfoQ写作社区