gpt4 book ai didi

使用 javac 8 编译代码时出现 Java 类型错误,但在 javac 6 中运行良好

转载 作者:搜寻专家 更新时间:2023-11-01 00:54:55 26 4
gpt4 key购买 nike

我有这个类,它是我在从 Java 6 移植到 Java 8 的项目中找到的一些代码的简化:

public class Unification {

final class Box<A> {}

final class MyMap<A, B extends Box<? extends A>> {}

MyMap<?, ?> getMap() {
return new MyMap<Object, Box<Object>>();
}

<A, B extends Box<? extends A>> void setMap(final MyMap<A, B> m) {}

void compileError() {
setMap(getMap());
}

}

这是一个非常小的例子,只是为了展示问题,实际的代码更有意义。这个问题似乎很普遍,因此是抽象的例子。核心问题如下:出于某种原因,javac 不想接受类型为 MyMap<?, ?> 的表达式。作为 setMap() 的参数方法,尽管根据我的理解,这应该是类型良好的。

使用 javac 6 编译代码没有错误,但是当我使用 javac 8 时,我收到这条模糊的错误消息:

C:\System9\KWS_sparse\sourcesNG\Domain\src\uz\Unification.java (21:9) error: method setMap in class Unification cannot be applied to given types;
required: Unification.MyMap<A,B>
found: Unification.MyMap<CAP#1,CAP#2>
reason: inference variable A has incompatible bounds
equality constraints: CAP#1
lower bounds: Object
where A,B are type-variables:
A extends Object declared in method <A,B>setMap(Unification.MyMap<A,B>)
B extends Unification.Box<? extends A> declared in method <A,B>setMap(Unification.MyMap<A,B>)
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends Object from capture of ?
CAP#2 extends Unification.Box<? extends CAP#1> from capture of ?

报错信息好像是MyMap的第一个类型参数找不到统一, javac 找不到与两者统一的类型 CAP#1 , 它表示 setMap() 的实际参数中的第一个通配符参数, 和 A ,即setMap()的形参对应的类型参数.尽管在我看来 ACAP#1应该是完全统一的,那么它们都将代表通过删除 getMap() 签名中的实际类型引入的存在类型.

谁能发现这里出了什么问题? javac 6 是否错误地接受了这段代码?此外,是否有一种不太侵入性(并且与 javac 6 兼容)的方法来引导 javac 8 实现正确的统一?

编辑:我尝试了从 stackoverflow.com/questions/23063474/引入变量的建议,但这似乎没有帮助,我得到了同样的编译错误。

EDIT2:阐明了示例代码的“意图”。

EDIT3:改名为MapMyMap , 显然定义自定义 Map 太困惑了类型。

最佳答案

这个问题可以通过引入一个中间方法来规避,从而强制 javac 分两个阶段进行类型推断。第一种方法只接受一个类型参数,将第二个类型参数保留为通配符。 Javac 能够正确地推断出此方法的单一类型参数。然后,第二个也是原始方法能够从提供的参数中正确推断出第二个类型参数。

public class Unification {

final class Box<A> {}

final class MyMap<A, B extends Box<? extends A>> {}

MyMap<?, ?> getMap() {
return new MyMap<Object, Box<Object>>();
}

<A> void setMap(final MyMap<A, ?> m) {
doSetMap(m);
}

<A, B extends Box<? extends A>> void doSetMap(final MyMap<A, B> m) {}

void worksFineNow() {
setMap(getMap());
}

}

关于使用 javac 8 编译代码时出现 Java 类型错误,但在 javac 6 中运行良好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40088515/

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