Java 如何实现接受消费者的方法<;可选<;T>&燃气轮机;这是T中的逆变?

Java 如何实现接受消费者的方法<;可选<;T>&燃气轮机;这是T中的逆变?,java,generics,generic-variance,Java,Generics,Generic Variance,在下面的示例中,我可以传递一个使用者原因是可选的从类型系统的角度来看并不特殊:我们知道可选的只有一个提供者方法(可选的.get()),而没有使用者方法(比如可选的.set(t));但是编译器没有 因此,编译器it不允许您在需要可选的情况下传递可选:它阻止您调用神秘的set方法,以防您传递的是双精度,而不是整数 解决此问题的唯一方法是将可选更改为可选,其中S是T的超类型。您可以通过以下任一方式完成此操作: 强制转换-您知道它是安全的,因为可选的不变性及其缺少消费者方法;但是您会得到一个未经检查的

在下面的示例中,我可以传递一个
使用者原因是
可选的
从类型系统的角度来看并不特殊:我们知道
可选的
只有一个提供者方法(
可选的.get()
),而没有使用者方法(比如
可选的.set(t)
);但是编译器没有

因此,编译器it不允许您在需要
可选
的情况下传递
可选
:它阻止您调用神秘的
set
方法,以防您传递的是
双精度
,而不是
整数

解决此问题的唯一方法是将
可选
更改为
可选
,其中
S
T
的超类型。您可以通过以下任一方式完成此操作:

  • 强制转换-您知道它是安全的,因为
    可选
    的不变性及其缺少消费者方法;但是您会得到一个未经检查的警告(由于
    Optional
    的属性,实际上可以抑制该警告)
  • 创建一个正确类型的新的
    可选的
    ——可能更纯粹,但是有创建新实例的运行时开销
为了在方法中编写这样的东西,您必须将其作为静态方法编写(可能在
test
类中,但也可能在其他地方);Java的类型系统表达能力不足,无法在实例方法的签名上写入所需的约束:

public static <T, S extends T> void foo3(Consumer<Optional<T>> c, test<S> test) {
    Optional<S> s = null;

    @SuppressWarnings("unchecked")  // Safe because of properties of Optional.
    Optional<T> t = (Optional<T>) (Optional<?>) s;

    c.accept(t);
}

public static <T, S extends T> void foo3(Consumer<Optional<T>> c, test<S> test) {
    Optional<S> s = null;

    @SuppressWarnings("unchecked")  // Safe because of properties of Optional.
    Optional<T> t = (Optional<T>) (Optional<?>) s;

    c.accept(t);
}
foo3(cri, t); // compiles
foo3(crn, t); // compiles