java - 在不失去通用性的情况下包装逆变函数接口(interface)

标签 java generics nested-generics

我有一些具有这种一般结构的代码:

interface Func<A> {
    double apply(Optional<A> a);
}

class Foo {
    public double compute(Func<Double> f) {
        // Sometimes amend the function to do something slightly different
        Func<Double> g = f;
        if (someCondition())
            g = oa -> Math.max(0, f.apply(oa));

        return g.apply(Optional.of(3.14)) + g.apply(Optional.empty());
    }
}

这本身就很有效。现在我想更自由一些,例如,如果有人有一个 Func<Number>Func<Object>而不是 Func<Double>他们仍然可以将其传递给 compute . 先验这应该是足够安全的。很好,所以我将其更改为

    public double compute(Func<? super Double> f) {
        Func<? super Double> g = f;
        if (someCondition())
            g = oa -> Math.max(0, f.apply(oa));
        ...

不幸的是,现在 lambda 不进行类型检查(Eclipse 说),因为 oa 的类型无法传递给 f.apply .

f的赋值本身到g编译器似乎并不担心,如果 apply 的参数不会出现问题是A而不是 Optional<A> .

不幸的是,似乎没有办法命名 ? super Double参数类型,以便我可以再次将其用作 g 的类型和/或用老式的内部类替换 lambda。

例如,这在句法上是不允许的:

    public <T super Double> double compute(Func<T> f) {
        Func<T> g = f;
        ...

是否有任何合理优雅的方式来完成这项工作?

到目前为止我想到的最好的是

    public double compute(Func<? super Double> f) {
        if (someCondition())
            return computeInner(oa -> Math.max(0, f.apply(oa)));
        else
            return computeInner(f);
    }

    private double computeInner(Func<? super Double> g) {
        return g.apply(Optional.of(3.14)) + g.apply(Optional.empty());
    }

编译器接受这一点,但除了让类型检查器高兴之外没有其他原因的间接调用并不是我所说的优雅。

最佳答案

试试这个奇怪的技巧:

g = oa -> Math.max(0, f.apply(oa.map(a -> a)));
                             // ^----------^

像这样映射可选类型允许编译器将可选类型“转换”为一致的类型。

Ideone demo

这确实有创建新的 Optional 实例的缺点。


但是,当然,I asked this question考虑这是否实际上是规范允许的事情,还是一个错误。


就我个人而言,我认为您的“迄今为止最好的”并没有特别过分。当然,这取决于真正的代码看起来如何。

关于java - 在不失去通用性的情况下包装逆变函数接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51331635/

相关文章:

java - Java操作系统怎么可能?

java - 了解 spring 集成服务激活器

java - 为什么为非泛型方法或构造函数提供显式类型参数会编译?

generics - rust:巨大的通用构造函数,嵌套特征

Java 获取封闭泛型类型的类常量(Class<T1<T2>> 的实例)

java - 为什么我不能分配给这个通用变量?

java - 如何在 OSGI 中使用 JSF 组件库

java - Android:Viewpager OnPageChangeListener onpageselected 干扰幻灯片动画

c# - 在泛型中实现算术?

c# - 使用泛型 C# 访问 const