【问题标题】:Generic bounded wildcard of function input type函数输入类型的通用有界通配符
【发布时间】:2015-08-21 11:35:10
【问题描述】:

在阅读Stream接口源代码时,我发现了这个方法签名:

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

我想知道为什么mapper的输入类型是? super T而输出类型是? extends R,为什么不同时使用? extends呢?

【问题讨论】:

标签: java generics java-8


【解决方案1】:

考虑您要将CharSequence 映射到另一个CharSequence(因此T = R = CharSequence)。哪些功能适合您?

Function<Object, String> fn1 = Object::toString;

对你有好处吗?是的,因为它可以采用 any CharSequence(也是 Object)并将其转换为 String(也是 CharSequence)。

Function<CharSequence, StringBuilder> fn2 = StringBuilder::new;

对你有好处吗?是的,因为它可以采用 any CharSequence 并将其转换为 StringBuilder(也是 CharSequence)。

Function<String, String> fn3 = String::trim;

对你有好处吗?不,因为它不能接受 任何 CharSequence,只能接受其中的一些。

因此您可以看到第一个类型参数必须是CharSequence 或任何超类,但第二个必须是CharSequence 或任何子类。

【讨论】:

    【解决方案2】:

    因为PECS :) - 生产者扩展,消费者超级

    Producer Extends - 如果你需要一个 List 来产生 T 值(你想从列表中读取 Ts),你需要用 ? extends T 声明它

    Consumer Super - 如果你需要一个List来消费T的值(你想将Ts写入list),你需要用? super T声明它

    【讨论】:

    • 这个答案虽然说的是正确的事实,但并没有直接回答问题。可以加一两句话说明它和上面提到的 Stream 方法有什么关系?
    【解决方案3】:

    Joshua Bloch 在他的Effective Java book 中首次提到了一条经验法则,即PECS

    • PE Producer 扩展
    • CS 超级消费者

    此函数根据它收到的内容 (? super T) 生成结果 (? extends R)

    java.util.Function 的文档对此很清楚:

    表示接受一个参数并产生结果的函数。

    【讨论】:

      猜你喜欢
      • 2015-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-14
      相关资源
      最近更新 更多