You wonder why isn't it supported? An equally valid question is, why should it be supported?
The way wildcards work, given the declaration X<? extends Y> x
, the type of the expression x.get()
is not ? extends Y
or some type inferred by the compiler, but Y
. Now, Y
isn't assignable to ? extends Y
, so you can't pass x.get()
to x.set
which has the effective signature of void set(? extends Y e)
. The only thing you could actually pass to it is null
, which is assignable to every reference type.
I follow the JDK developer mailing lists fairly closely, and the general spirit there is that every feature the JLS specifies should pull its own weight - the cost/benefit ratio should be heavy on the benefit side. Now, keeping track of the origin of a value would be quite possible, but it would only solve one special case, which has several other ways to solve it. Consider these classes:
class ClientOfX {
X<?> member;
void a(X<?> param) {
param.set(param.get());
}
void b() {
X<?> local = new XImpl<Object>();
local.set(local.get());
}
void c() {
member.set(member.get());
}
void d() {
ClassWeCantChange.x.set(ClassWeCantChange.x.get());
}
}
class ClassWeCantChange {
public static X<?> x;
}
This obviously doesn't compile, but with your proposed enhancement, it does. However, we can get three of the four methods compiling without changing the JLS:
- For
a
, when we receive the generic object as a parameter, we can make the method generic and receive an X<T>
instead of X<?>
.
- For
b
and c
, when using a locally declared reference, we don't need to declare the reference with a wildcard (Eric Lippert of Microsoft's C# compiler team calls this situation "if it hurts when you do that, then don't do that!").
- For
d
, when using a reference whose declaration we can't control, we have no option but to write a helper method.
So the smarter type system would really only help in the case where we can't control the declaration of a variable. And in that situation, the case for doing what you want to do is kind of sketchy - the very act of wildcarding a generic type normally means that the object is either intended to work only as a producer (? extends Something
) or a consumer (? super Something
) of objects, not both.
The TL;DR version is that it would bring little benefit (and require wildcards to be something else than what they are today!) while adding complexity to the JLS. If someone comes up with a very compelling case to add it, the spec could be extended - but once it's there, it's there forever, and it may cause unforeseen problems down the road, so leave it out until you really need it.
Edit: The comments contain more discussion about what wildcards are and aren't.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…