首页 > 解决方案 > 何时使用生产者和消费者逻辑/通配符 JAVA

问题描述


有人可以帮助我理解这段代码背后的逻辑:

import java.util.List;
import java.util.Arrays;

interface DoubleValue<T> {
    public void dv(T e);
}

public class InTest2 {

    public static void main(String[] a) {
        DoubleValue<Number> func = e -> System.out.println(e.doubleValue());
        List<Number> l = Arrays.asList(1, 2, 3);
        InTest2.sumOfListNotWorking(l, func);
        InTest2.sumOfListWorking(l, func);
        InTest2.sumOfListWorkingSuper(l, func);
    }

    // I thought this should work
    public static void sumOfListNotWorking(List<? extends Number> list, DoubleValue<? extends Number> f) {
        for (Number n : list)
            f.dv(n);  // This line give error: The method dv(capture#2-of ? extends Number) in the type DoubleValue<capture#2-of ? extends Number> is not applicable for the arguments (Number)
    }

    public static void sumOfListWorking(List<? extends Number> list, DoubleValue<Number> f) {
        for (Number n : list)
            f.dv(n);
    }

    public static void sumOfListWorkingSuper(List<? extends Number> list, DoubleValue<? super Number> f) {
        for (Number n : list)
            f.dv(n);
    }
}

sumOfListNotWorking:
这里我传给DoubleValue.dv(<? extends Number> e)一个数字,我觉得没问题。但是编译器说不是。为什么?
我期望DoubleValue<Number>.dve -> e.doubleValue()应该是典型的消费者:我得到价值<? extends Number>并用它做点什么。


sumOfListWorkingSuper:
的行为也sumOfListWorkingSuper让我很困惑。接口DoubleValue<? super Number>不能是消费者,因为<? super Number>不能就地更改值(数字是不可变的),但编译器可以接受。

更新:
显然我没有正确理解“生产者”和“消费者”的逻辑。

sumOfListNotWorking:
此方法无法编译,因为我使用:

感谢您在消费者和生产者的逻辑中指出“接受”一词。

标签: java

解决方案


List<? extends Number>意思是“我们不知道这个 List 包含什么,但不管它是什么,它都是 Number 或 Number 本身的后代。”

同样,DoubleValue<? extends Number>意味着“我们不知道这个 DoubleValue 可以接受什么来操作,但无论它接受什么,它都是 Number 或 Number 本身的后代”。

这里的相关部分是“我们不知道它接受什么”。我们不知道,所以你不能给它任何东西并期望它会被接受:因为你不知道它是否被接受。其余信息无关紧要。它在 a 中是相关的,List<? extends Number>因为至少我们知道它给出的任何元素都可以在给出之后安全地转换为 Number 。但是你的 DoubleValue 类并没有给出任何东西。它只接受东西。所以所有那些“但我们知道它是它的后代”是完全没用的。

<? extends Stuff>在给出对象的类上很有用。对于那些不给出对象的人来说,它是没有用的。

<? super Stuff>在接受对象的类上很有用。对于那些不接受对象的人来说,它是无用的。


推荐阅读