gpt4 book ai didi

java - 不兼容类型 : Class cannot be converted to Class where CAP#1 is a fresh-type variable

转载 作者:行者123 更新时间:2023-11-30 10:43:29 27 4
gpt4 key购买 nike

我在编写一些代码时遇到了一些让我烦恼的事情。我在下面的代码示例中收集了这两个示例。

cls1 行使用 lambda 表达式但不编译,而 cls2 行使用方法引用并编译。我知道如果我使用非泛型对象,我不会有任何问题,但在这里,我使用的是泛型,更具体地说,是通配符。

import java.lang.annotation.*;
import java.util.Optional;

public class MCVE {

static class Foo {}
static class Bar extends Foo {}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
static @interface Baz { Class<? extends Foo> value(); }

@Baz(Bar.class)
static class Quz {}

// Lambda expression - doesn't compile
Class<? extends Foo> cls1 = Optional.ofNullable(Quz.class.getAnnotation(Baz.class))
.map(baz -> baz.value())
.orElse(Bar.class);

// Method reference - compiles
Class<? extends Foo> cls2 = Optional.ofNullable(Quz.class.getAnnotation(Baz.class))
.map(Baz::value)
.orElse(Bar.class);

}

在功能上,两条线都在做同样的事情。所以我只是不明白是什么导致 lambda 表达式的使用失败而方法引用没有问题。

对于那些会问的人,编译时收到的错误如下:

MCVE.java:25: error: incompatible types: Class<Bar> cannot be converted to Class<CAP#1>
.orElse(Bar.class);
^
where CAP#1 is a fresh type-variable:
CAP#1 extends Foo from capture of ? extends Foo
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error

这相当简洁,没有提供任何非常有用的信息。

另外,请注意,我已经完成了研究,这个错误与您在右侧面板上看到的“类似问题”中的错误不同。这里有趣的部分是“新鲜类型变量”。

最佳答案

假设您有 3 个类:

static class Foo {}
static class Bar extends Foo {}
static class Dem extends Foo {}

编译器将从 lambda 表达式中找到:

var x1 = Optional.ofNullable(Quz.class.getAnnotation(Baz.class));
// typeof x1 = Optional<Baz>

var x2 = x1.map(baz -> baz.value())
// typeof x2 = Optional<Class<T>>, where <T extends Foo> - this is the black magic you suffer with
// E.g. it can be
// a) Optional<Class<T=Foo>> or
// b) Optional<Class<T=Bar>> or
// c) Optional<Class<T=Dem>>

var x3 = x2.orElse(Bar.class);
// In case (a) and (b) - this code should work, in case (c) it should fail.
// Without additional explicit hint (conversion) compiler reports about this issue.

当你使用方法引用时——编译器忽略描述的类型推断并使用原始的 Baz 类型声明,所以

.map(Baz::value) // is identical to
.map(baz -> (Class<? extends Foo>) baz.value())

关于java - 不兼容类型 : Class<Bar> cannot be converted to Class<CAP#1> where CAP#1 is a fresh-type variable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37736824/

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