gpt4 book ai didi

java - 关于Java泛型和java.util.function.Function设计的问题

转载 作者:行者123 更新时间:2023-11-30 05:31:06 24 4
gpt4 key购买 nike

  1. 有关通配符的问题

示例:Student extends Person

    Person person = new Person();
Student student = new Student();

List<? super Student> list = new ArrayList<>();
list.add(student); // success
list.add(person); // compile error

List<? extends Person> list2 = new ArrayList<>();
list2.add(person); // compile error
list2.add(student);// compile error

我已阅读问题“capture#1-of ? extends Object is not applicable”下面的答案

You are using generic wildcard. You cannot perform add operation as class type is not determinate. You cannot add/put anything(except null) -- Aniket Thakur

Official doc:The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype

但是为什么可以list.add(student)编译成功

  • java.util.function.Function的设计
  • public interface Function<T, R>{

    //...

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
    }
    }

    为什么before旨在 Function<? super V, ? extends T>而不是Function<V,T>当返回类型为Function<V,R>时输入的类型是 V ? (仍可通过编译,灵活使用)

    最佳答案

    要理解这些问题,您必须了解泛型如何与 subtyping 一起工作。 (在 Java 中使用 extends 关键字明确表示)。安德烈亚斯提到 PECS规则,这是它们在 Java 中的表示。

    首先,我想指出上面的代码可以通过简单的强制转换来纠正

    ArrayList<? super Student> list = new ArrayList<>();
    list.add(new Student());
    ArrayList<Person> a = (ArrayList<Person>) list; // a covariance
    a.add(new Person());

    并且编译和运行良好(而不是引发任何异常)

    原因很简单,当我们有 consumer 时(它获取一些对象并使用它们,例如 add 方法),我们期望它获取 no more than 类型的对象(父类(super class))类型 T我们指定,因为消费过程可能需要它想要的类型的任何成员(变量、方法等),并且我们要确保类型 T满足消费者所需的所有成员(member)。

    相反,producer为我们生成对象(如 get 方法),必须提供 no less than 类型的对象。指定类型T这样我们就可以访问 T 的任何成员已在生成的对象上。

    这两个与名为 covariance 的子类型表单密切相关。和contravariance

    关于第二个问题,可以引用 Consumer<T> 的实现以及(稍微简单一些):

    default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
    }

    我们需要这个的原因? super T是这样的:当我们组合两个 Consumer 时使用方法andThen ,假设前者Consumer接受 T 类型的对象,我们期望后者采用 no more than T 类型的对象所以它不会尝试访问 T 的任何成员没有。

    因此,而不是简单地写Consumer<T> after但是Consumer<? super T> after ,我们允许前一个消费者( T 类型)与一个接受不完全类型 T 的对象的消费者组合。 ,但可能小于 T ,方便的话 covariance 。这使得以下代码听起来:

    Consumer<Student> stu = (student) -> {};
    Consumer<Person> per = (person) -> {};
    stu.andThen(per);

    compose类型的方法Function出于同样的考虑,也适用。

    关于java - 关于Java泛型和java.util.function.Function设计的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57549932/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com