gpt4 book ai didi

java - 为什么此代码仅使用冗余 map() 进行编译?

转载 作者:行者123 更新时间:2023-12-01 14:17:04 25 4
gpt4 key购买 nike

我遇到了一个我无法解释的怪事。

以下代码(最小示例)不会编译:

class Test {
interface I {}

Optional<I> findOne(ArrayList<? extends I> list) {
return list.stream()
.findFirst();
}
}

javac(至少版本 11)说:

error: incompatible types: Optional<CAP#1> cannot be converted to Optional<I>
.findFirst();
^
where CAP#1 is a fresh type-variable:
CAP#1 extends I from capture of ? extends I

但是,我随机发现向流添加一个看似多余的 .map() 调用 [edit:它实际上被添加到 findFirst() 返回的 Optional 中] 编译得很好:

class Test {
interface I {}

Optional<I> findOne(ArrayList<? extends I> list) {
return list.stream()
.findFirst()
.map(a -> a);
}
}

我很好奇那里发生了什么,添加 .map() 调用可以让它编译。<​​/p>

[我知道更改方法参数以获取 ArrayList<I>有效,但这不是我要问的。]

最佳答案

泛型是不变的

第一个无法编译,因为 Java 泛型是不变的

Optional<Dog>Optional<Animal> 完全不同,因此 Optional<...>...成为你的类型 ?捕获与 Optional<I> 不兼容.

为了详细说明,请考虑以下示例:

List<Dog> dogs = new ArrayList<>();

List<Animal> animals = dogs; // this does not compile, but pretend it would
animals.add(new Cat());

Dog dog = dogs.get(0); // should be safe, but its actually a cat!

上行

但是有了 map(a -> a)你有一个类型的隐式向上转换,比如(Animal) dog这实际上是一个 Optional<Animal> .所以Optional<I>而不是 Optional<...>在你的情况下。

所以你的 a -> a看起来无辜的lambda实际上是一种采用Dog的方法(或在你的情况下来自 ...?)并给出一个 Animal (或 I ):

a -> (I) a

考虑下面的例子

Optional<Dog> dog = Optional.of(new Dog());

Optional<Animal> animal = dog.map(d -> d);

这恰好说明了您的情况。由于不变性,你不能只是分配它,你必须主动转换它。并且由于上下文,Java 可以隐式转换 d。至 Animal .所以代码等同于

dog.map(d -> (Animal) d);

注意事项

请注意 map您在此处调用的方法不是 map来自 Stream但来自 Optional ,这是 findFirst 的结果.所以它的目的是从 Optional<X> 映射到Optional<Y>通过应用给定的转换。

关于java - 为什么此代码仅使用冗余 map() 进行编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61781355/

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