I've always been wondering about some weird aspect of Java generics and the use of wildcards. Let's say, I have the following API:
public interface X<E> {
E get();
E set(E e);
}
And then, let's say we declare the following methods:
public class Foo {
public void foo(X<?> x) {
// This does not compile:
x.set(x.get());
}
public <T> void bar(X<T> x) {
// This compiles:
x.set(x.get());
}
}
From my "intuitive" understanding, X<?>
is in fact the same as X<T>
, except that the unknown <T>
is formally unknown to client code. But inside of foo()
, I would guess that the compiler could infer (pseudo JLS code) <T0> := <?>[0], <T1> := <?>[1], etc...
. This is what most programmers do explicitly and intuitively. They delegate to a private helper method, which leads to a lot of useless boiler-plate code:
public class Foo {
public void foo(X<?> x) {
foo0(x);
}
private <T> void foo0(X<T> x) {
x.set(x.get());
}
}
Another example:
public class Foo {
public void foo() {
// Assuming I could instanciate X
X<?> x = new X<Object>();
// Here, I cannot simply add a generic type to foo():
// I have no choice but to introduce a useless foo0() helper method
x.set(x.get());
}
}
In other words, the compiler knows that the wildcard in x.set()
is formally the same as the wildcard in x.get()
. Why can't it use that information? Is there a formal aspect in the JLS, that explains this lacking compiler "feature"?