标签:

上一篇博文java8函数式编程--收集器collector:(http://my.oschina.net/joshuashaw/blog/487322)讲得比较随性,并没有把源码一句一句拿出来分析,后来发现groupingBy方法最后有一个if-else分支用来返回不同类型的collector,一个是不需要特定finisher的,另一个需要使用下游收集器的finisher,今天细看源码,发现了几句神奇的代码,拿出来讲一讲。

先贴源码:

public static >

Collector groupingBy(Function super T, ? extends K> classifier,

Supplier mapFactory,

Collector super T, A, D> downstream) {

Supplier downstreamSupplier = downstream.supplier();

BiConsumer downstreamAccumulator = downstream.accumulator();

BiConsumer, T> accumulator = (m, t) -> {

K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");

A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());

downstreamAccumulator.accept(container, t);

};

BinaryOperator> merger = Collectors.>mapMerger(downstream.combiner());

@SuppressWarnings("unchecked")

Supplier> mangledFactory = (Supplier>) mapFactory;

if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {

return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);

}

else {

/*---------------------------

----    --神奇的代码--   ------

-----------------------------

@SuppressWarnings("unchecked")

Function downstreamFinisher = (Function) downstream.finisher();

Function, M> finisher = intermediate -> {

intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));

@SuppressWarnings("unchecked")

M castResult = (M) intermediate;

return castResult;

};

-----------------------------

-----  ---神奇的代码-----  ----

--------------------------*/

return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);

}

}

抽出来强调一下

@SuppressWarnings("unchecked")

Function downstreamFinisher = (Function) downstream.finisher();

Function, M> finisher = intermediate -> {

intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));

@SuppressWarnings("unchecked")

M castResult = (M) intermediate;

return castResult;

};

这里我们看到,类型为

(Function) downstream.finisher()

被强制类型转换成

(Function) downstreamFinisher

然后是

Map intermediate

被强制类型转换成

Map intermediate

我想,这都行?于是我写了两条语句

Fuction f1 = Integer::parse;

Fuction f2 = (Fuction) f1;

编译器报错。

但是为什么groupingBy方法里面可以这样写?于是我按照groupingBy方法写了一个测试类,代码如下:

import java.util.HashMap;

import java.util.Map;

import java.util.function.Function;

public class InterestingTest {

private Map Tmap = null;

private Map Vmap = null;

private Function Vf = null;

private Function Tf = null;

public InterestingTest(Map m,Function f){

Tmap = m;

Vf = f;

Tf = (Function) f;

Tmap.replaceAll((k,t)->Tf.apply(t));

Vmap = (Map) Tmap;

}

public Map getMap(){

return Vmap;

}

public static void main(String[] args) {

Map map = new HashMap<>();

map.put("1", 1);

map.put("2", 2);

map.put("3", 3);

map.put("4", 4);

Map newMap =

new InterestingTest(map,Integer::toBinaryString)

.getMap();

newMap.entrySet().stream()

.forEach(e->{System.out.println(e.getKey()+" "+e.getValue());});

}

}

代码只是报警告,一运行下来一点问题都没有,完美得出结果。

几天前刷知乎看到java实现不了真正的泛型,现在算是明白了。

其实,对于java泛型的实现,只是编译器在编译阶段帮助你进行类型转型,像Map类型,实际是保存你的对象的地址,对于Map来说,他只是存了Integer的地址,将Integer视为终极父类Object的子类,当你调用get(key)的时候,最后返回Object类型给你之前帮你强制类型转换成了Integer,就像:

put(key,IntegerObject){

this.object = IntegerObject;

}

get(key){

return (Integer) findCorrentObject;

}

所以从泛型的角度看,代码没有错误,但是会警告你这代码可能导致类型转换而出现的错误,于是我们可以看到

@SuppressWarnings("unchecked")

来去除警告。

但是,当你使用的是具体的类型时,编译器有职责给你报错,他认为你写的这行代码很有可能发生错误。

总结:都是兼容和初始开发人员省事而留下的问题啊。

标签:

java 泛型 .net_Java泛型相关推荐

  1. java 泛型 .net_Java基础11:Java泛型详解

    本文对java的泛型的概念和使用做了详尽的介绍. 本文参考https://blog.csdn.net/s10461/article/details/53941091 具体代码在我的GitHub中可以找 ...

  2. Java中创建泛型数组

    Java中创建泛型数组 使用泛型时,我想很多人肯定尝试过如下的代码,去创建一个泛型数组 T[] array = new T[]; 当我们写出这样的代码时编译器会报Cannot create a gen ...

  3. 2015第22周六Java反射、泛型、容器简介

    Java的反射非常强大,传递class, 可以动态的生成该类.取得这个类的所有信息,包括里面的属性.方法以及构造函数等,甚至可以取得其父类或父接口里面的内容. obj.getClass().getDe ...

  4. Java中的泛型 --- Java 编程思想

    前言 ​ 我一直都认为泛型是程序语言设计中一个非常基础,重要的概念,Java 中的泛型到底是怎么样的,为什么会有泛型,泛型怎么发展出来的.通透理解泛型是学好基础里面中非常重要的.于是,我对<Ja ...

  5. java泛型的泛型_Java 泛型总结(一):基本用法与类型擦除

    简介 Java 在 1.5 引入了泛型机制,泛型本质是参数化类型,也就是说变量的类型是一个参数,在使用时再指定为具体类型.泛型可以用于类.接口.方法,通过使用泛型可以使代码更简单.安全.然而 Java ...

  6. 14. Java基础之泛型

    一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: 1 public class GenericTest { 2 3 public static void main(Stri ...

  7. 【Java 泛型】泛型用法 ( 泛型编译期擦除 | 上界通配符 <? extends T> | 下界通配符 <? super T> )

    文章目录 一.泛型擦除 二.泛型的上界通配符 <? extends T> 三.泛型的下界通配符 <? super T> 一.泛型擦除 泛型只保留到 编译期 , 在 编译完毕后 ...

  8. 【Java 泛型】泛型用法 ( 泛型类用法 | 泛型方法用法 | 泛型通配符 ? | 泛型安全检查 )

    文章目录 一.泛型类用法 二.泛型方法用法 三.泛型通配符 <?> 四.泛型安全检查 五.完整代码示例 1.泛型类 / 方法 2.main 函数 一.泛型类用法 泛型类用法 : 使用时先声 ...

  9. 【Java 泛型】泛型简介 ( 泛型类 | 泛型方法 | 静态方法的泛型 | 泛型类与泛型方法完整示例 )

    文章目录 一.泛型简介 二.泛型类 三.泛型方法 四.静态方法的泛型 五.泛型类与泛型方法完整示例 一.泛型简介 泛型 可以 简单理解为 参数化类型 , 主要作用在 类 , 方法 , 接口 上 ; j ...

最新文章

  1. 美观实用!Star 过万,用 Python 做交互式图形的这款工具火了!
  2. rcnn 改进mask_李沐团队提出最强ResNet改进版,多项任务达到SOTA | 已开源
  3. Eclipse中server启动超时的解决方法
  4. for,while循环
  5. OPA 6 - module(Create Button Test);
  6. ASP.NET MVC 2.0 AsyncController(转)
  7. C语言 数组中删除指定字符
  8. IT4IT的前世今生
  9. 女人需谨记的十六条健康戒律
  10. 内联函数let、also、with、run、apply的用法
  11. 游戏手柄计算机,电脑游戏手柄怎么设置 电脑游戏手柄设置步骤【图文】
  12. 【PDF下载】三本机器学习统计学入门好书
  13. 软件开发搞定计算机组成原理:计算篇
  14. 教师计算机基础知识培训简报,信息技术能力提升培训简报.doc
  15. 漩涡中的中国首富李彦宏
  16. 如何创建和编写项目管理计划?
  17. webp 项目总结以及思考
  18. 读者让我总结一波 redis 面试题,现在肝出来了!
  19. 达梦数据库喜中国家电网公司信息化软件框架采购竞争性谈判项目
  20. 月薪5K跟月薪5W的程序员,写出来的代码有什么差别?

热门文章

  1. 开放共赢,华为云WeLink生态联盟正式成立!
  2. 要闻君说:台积电将为iPhone生产5纳米A系列芯片?腾讯云TStack与银河麒麟完成互认证……...
  3. 【拨云见日】企业上云时代,多样化的公有云服务你了解多少?
  4. vos3000落地网关对接教学_跨国合作:Serverless Components 在腾讯云的落地和实践
  5. apache 统计404日志_Apache监控与调优(四)Apachetop监控
  6. 中油即时通信电脑版_市场营销之即时通讯营销
  7. html5 烟雾,jQuery烟雾背景发生器(HTML5 Canvas插件waterpipe.js
  8. Nacos 集群集成SpringBoot2.x 微服务_02
  9. MyBatisPlus_AR篇_入门试炼_06
  10. JavaScript-概述