最大可选流会导致“不兼容类型”编译错误

问题描述 投票:0回答:1

我遇到了一个编译器问题,我可以将其简化为这个示例。这段代码

class A<T> {
    Optional<Integer> op;

    public Optional<Integer> getOp() {
        return op;
    }
}
List<A> l = null;
l.stream().map(x -> x.getOp().orElse(0)).max(Comparator.naturalOrder());

无法编译

error: incompatible types: inference variable T has incompatible bounds
    [javac]         l.stream().map(x -> x.getOp().orElse(0)).max(Comparator.naturalOrder());
    [javac]                                                                             ^

如果我删除通用参数

<T>
(类中根本没有使用),则此代码片段将编译。这是怎么回事?我正在使用 Java 8。

java generics java-8 java-stream option-type
1个回答
0
投票

这里的问题是在

A
中使用原始类型
List<A>
,而不是通用类型(例如
List<A<?>>
)。 将
l
的类型从
List<A>
更改为
List<A<?>>
足以解决编译问题。

List<A<?>> l = null;

问题分解

由于

A
是原始类型,
getOp
返回
Optional
,而不是
Optional<Integer>
。 由于特定类型未知,因此
x.getOp().orElse(0)
返回
Object
而不是
Integer
Comparator.naturalOrder()
只能比较
Comparable
值,
Object
则不能。 因此编译失败在
.max(Comparator.naturalOrder())

避免原始类型

Java 语言规范 解释说,原始类型只是为了支持前通用(Java 4 及更早版本)代码而存在,并且特别不鼓励在新代码中使用原始类型:

为了方便与非泛型遗留代码的接口,可以使用参数化类型(§4.5)的擦除(§4.6)或数组类型(§10.1)的擦除作为类型其元素类型是参数化类型。这样的类型称为 raw 类型

[…]

仅允许使用原始类型作为对遗留代码兼容性的让步。强烈建议不要在 Java 编程语言中引入泛型之后编写的代码中使用原始类型。 Java 编程语言的未来版本可能会禁止使用原始类型。

© www.soinside.com 2019 - 2024. All rights reserved.