泛型的理解:

在创建对象或者调用方法的时候才明确下具体的类型。

使用泛型的好处

就是代码更加的简洁(不需要强制转化),程序更加的健壮(在编译期间没有警告,在运行期就不会出现ClassCastException异常)。

平时工作中是否使用?

在操作集合的时候,还是很多的,毕竟方便啊。List lists = new ArrayList<>();

还在其他的场景使用吗?

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

这块可以参考springData jpa的JpaRepository写法。

  1. public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
  2. List<T> findAll();
  3. List<T> findAll(Sort sort);
  4. List<T> findAllById(Iterable<ID> ids);
  5. <S extends T> List<S> saveAll(Iterable<S> entities);
  6. void flush();
  7. <S extends T> S saveAndFlush(S entity);
  8. void deleteInBatch(Iterable<T> entities);
  9. void deleteAllInBatch();
  10. T getOne(ID id);
  11. @Override
  12. <S extends T> List<S> findAll(Example<S> example);
  13. @Override
  14. <S extends T> List<S> findAll(Example<S> example, Sort sort);
  15. }
  1. 要写组件还是离不开Java反射机制(能够从运行时获取信息),所以一般组件是泛型+反射来实现的。
  2. 回到所讲的组件,这边有一个需求,根据某些字段进行聚合。
  3. 换到SQL就是:

    1. select sum(column1),sum(column2) from table group by filed1,field2;
  4. 我们需要根据sum和group by的列肯定是由业务方自己传入,而sql的表其实就是我们的pojo(传入的字段也肯定是pojo的属性)。

  5. 单个业务实际可以在参数上写死pojo,但为了做到更加的通用,我们把入参设置为泛型。
  6. 拿到参数后,通过反射获取其字段具体的值,做累加就好了。
  7. 上代码: ```java // 传入 需要group by 和 sum 的字段名 public cacheMap(List groupByKeys, List sumValues) { this.groupByKeys = groupByKeys; this.sumValues = sumValues; }

private void excute(T e) {

// 从pojo 取出需要group by 的字段 list List 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(“类型异常,请处理异常”); } }

  1. // 处理时间记录
  2. Field field = getDeclaredField("updated", value);
  3. if (null != field) {
  4. field.set(value, DateTimeUtils.getCurrentTime());
  5. }

} else { // group by 字段 第一次进来 try { primaryMap.put(key, Tclone(e)); createdMap.put(key, DateTimeUtils.getCurrentTime()); }catch (Exception ex) { log.info(“first put value error {}” , e); } } } ```

  1. 理解泛型之后,再去检视自己代码时候,就可以判断是否需要用到泛型了。