为什么涉及通配符的此分配在Java中合法? [英] Why is this assignment involving wildcards legal in Java?
问题描述
关于通配符的大多数问题都想知道为什么编译器拒绝明智的选择.我的问题是相反的.为什么编译器接受以下程序?
Most questions about wildcards want to know why something sensible is rejected by the compiler. My question is the opposite. Why is the following program accepted by the compiler?
void test(List<? extends Number> g1, List<? extends Number> g2)
{
g1 = g2;
}
我试图从Java语言规范中对此进行解释,但是我没有找到答案.从Java泛型和通配符的各种描述中,我得到的印象是,通配符的每次使用都被捕获为一种全新的类型,但显然不在这里.我尚未发现允许此分配执行任何令人讨厌的行为,但仍然看起来错误".
I tried to explain this from the Java Language Specification, but I have not found the answer. I had the impression from various descriptions of Java generics and wildcards that each use of a wildcard is captured as a completely new type, but apparently not here. I have not found any nasty behavior that follows from this assignment being allowed, but it still seems "wrong".
推荐答案
当我面对这些问题时,我会以略有不同的方式来解决这个问题.
When I face these questions, I approach this in a slightly different manner.
首先,每个通配符
均由 javac
进行捕获
,无处不在
.用简单的英语来说:每次 javac
"sees"一个<通配符,它将进行转换(这将几乎准确,您将进一步看到).具体来说,假设我们有以下内容:
First of all, every single wildcard
is captured
, everywhere
, by javac
. In plain english: every time javac
"sees" a wildcard
it is going to transform that (this is almost accurate as you will see further). Specifically, let's say we have this:
List<? extends Number> list;
javac
将转换为:
List<X1> list
其中 X1< ;:数字
,其中<:
表示它是的子类型,例如: X1是扩展Number的未知类型
.每次发生都会发生这种情况.在某些情况下,一开始它可能很奇怪:
where X1 <: Number
, where <:
means it is a subtype of, as such : X1 is an unknown type that extends Number
. This will happen for every single occurrence. And it might be very weird, at first, in some scenarios:
public static void main(String[] args) {
List<?> l = new ArrayList<String>();
one(l);
two(l, l); // fails
}
public static <T> void one(List<T> single){
}
public static <T> void two(List<T> left, List<T> right){
}
捕获转换分别应用于每个 List
,就像这样:
capture conversion was applied individually to each List
, it's like this happened:
two(List<X1>, List<X2>)