上一篇博文java8函数式编程--收集器collector:(http://my.oschina.net/joshuashaw/blog/487322)讲得比较随性,并没有把源码一句一句拿出来分析,后来发现groupingBy方法最后有一个if-else分支用来返回不同类型的collector,一个是不需要特定finisher的,另一个需要使用下游收集器的finisher,今天细看源码,发现了几句神奇的代码,拿出来讲一讲。
先贴源码:
public static <T, K, D, A, M extends Map<K, D>> Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream) { Supplier<A> downstreamSupplier = downstream.supplier(); BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator(); BiConsumer<Map<K, A>, 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<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner()); @SuppressWarnings("unchecked") Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory; if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID); } else { /*--------------------------- ---- --神奇的代码-- ------ ----------------------------- @SuppressWarnings("unchecked") Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher(); Function<Map<K, A>, 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<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher(); Function<Map<K, A>, M> finisher = intermediate -> { intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v)); @SuppressWarnings("unchecked") M castResult = (M) intermediate; return castResult; };
这里我们看到,类型为
(Function<A, D>) downstream.finisher()
被强制类型转换成
(Function<A, A>) downstreamFinisher
然后是
Map<K,A> intermediate
被强制类型转换成
Map<K,D> intermediate
我想,这都行?于是我写了两条语句
Fuction<String,Integer> f1 = Integer::parse; Fuction<String,String> f2 = (Fuction<String,String>) f1;
编译器报错。
但是为什么groupingBy方法里面可以这样写?于是我按照groupingBy方法写了一个测试类,代码如下:
import java.util.HashMap; import java.util.Map; import java.util.function.Function; public class InterestingTest<K,T,V> { private Map<K,T> Tmap = null; private Map<K,V> Vmap = null; private Function<T,V> Vf = null; private Function<T,T> Tf = null; public InterestingTest(Map<K,T> m,Function<T,V> f){ Tmap = m; Vf = f; Tf = (Function<T, T>) f; Tmap.replaceAll((k,t)->Tf.apply(t)); Vmap = (Map<K, V>) Tmap; } public Map<K, V> getMap(){ return Vmap; } public static void main(String[] args) { Map<String,Integer> map = new HashMap<>(); map.put("1", 1); map.put("2", 2); map.put("3", 3); map.put("4", 4); Map<String,String> newMap = new InterestingTest<String,Integer,String>(map,Integer::toBinaryString) .getMap(); newMap.entrySet().stream() .forEach(e->{System.out.println(e.getKey()+" "+e.getValue());}); } }
代码只是报警告,一运行下来一点问题都没有,完美得出结果。
几天前刷知乎看到java实现不了真正的泛型,现在算是明白了。
其实,对于java泛型的实现,只是编译器在编译阶段帮助你进行类型转型,像Map<String,Integer>类型,实际是保存你的对象的地址,对于Map来说,他只是存了Integer的地址,将Integer视为终极父类Object的子类,当你调用get(key)的时候,最后返回Object类型给你之前帮你强制类型转换成了Integer,就像:
put(key,IntegerObject){ this.object = IntegerObject; } get(key){ return (Integer) findCorrentObject; }
所以从泛型的角度看,代码没有错误,但是会警告你这代码可能导致类型转换而出现的错误,于是我们可以看到
@SuppressWarnings("unchecked")
来去除警告。
但是,当你使用的是具体的类型时,编译器有职责给你报错,他认为你写的这行代码很有可能发生错误。
总结:都是兼容和初始开发人员省事而留下的问题啊。