为什么Java无法协调来自不同源的`?`泛型类型。

huangapple 未分类评论56阅读模式
英文:

Why java cannot reconcile the `?` generic type from different sources

问题

我有一个(据我理解)针对特定领域的单子(Monad),它充当了Either/Try的组合和用于REST终端点调用的操作。这是一个带有单一类型泛型参数的类,用于其包含的值。因为某些函数仅用于副作用而不关心返回值,我通常将它们的返回值简单地注释为MyMonadThing<?>。然而,这种模式在尝试在某些地方分叉逻辑时会引发问题。我不会展示单子类,但是这里有一个使用列表的示例,说明了问题:

public static void main(String[] args) {
    map(Arrays.asList(1, 2, 3), t -> {
        return t == 2? foo() : bar();
    });
}

static <T, NewT> List<NewT> map(List<T> lst, Function<T, List<NewT>> fn) {
    return lst.stream().flatMap(t -> fn.apply(t).stream()).collect(Collectors.toList());
}

static List<?> foo() {
    return Arrays.asList("foo");
}

static List<?> bar() {
    return Arrays.asList("bar");
}

这不会编译,因为三元运算符。出现以下错误:

  • 类型不匹配:无法从List<capture#2-of ?>转换为List

    我可以通过强制转换来修复这个问题(即return (List<?>) (t == 2? foo() : bar());),但这只是奇怪的。假设Java允许这样运行,那么main中的结果将简单地是List<?>类型,那么在什么情况下,由于不稳定的类型系统,这可能导致实际错误呢?

    英文:

    I have a (as I understand) monad in place made for specific domain, which acts as a combination of Either/Try and an action for rest endpoint call. It's a class with a single type generic parameter for it's contained value. Because some functions are only written for side effect and don't care for return value, I commonly annotated their return simply as MyMonadThing&lt;?&gt;. However, such pattern gives me issue when trying to fork logic at some places. I won't show the monad class, but here is example using lists that illustrates the problem

    public static void main(String[] args) {
    	map(Arrays.asList(1, 2, 3), t -&gt; {
    		return t == 2? foo() : bar();
    	});
    }
    
    static &lt;T, NewT&gt; List&lt;NewT&gt; map(List&lt;T&gt; lst, Function&lt;T, List&lt;NewT&gt;&gt; fn) {
    	return lst.stream().flatMap(t -&gt; fn.apply(t).stream()).collect(Collectors.toList());
    }
    
    static List&lt;?&gt; foo() {
    	return Arrays.asList(&quot;foo&quot;);
    }
    
    static List&lt;?&gt; bar() {
    	return Arrays.asList(&quot;bar&quot;);
    }
    

    This won't compile because of ternary.

    - Type mismatch: cannot convert from List&lt;capture#2-of ?&gt; to 
     List&lt;Object&gt;
    

    I can fix this by casting (ie return (List&lt;?&gt;) (t == 2? foo() : bar());) but that's just odd. Suppose java did allow this to run, and the result in main would be simply of type List&lt;?&gt; -- under what circumstances could this result in an actual error due to unsound type system?

    huangapple
    • 本文由 发表于 2020年5月5日 18:27:38
    • 转载请务必保留本文链接:https://java.coder-hub.com/61610965.html
    匿名

    发表评论

    匿名网友

    :?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

    确定