私はいつも、Javaジェネリックの奇妙な側面とワイルドカードの使用について疑問に思っていました。たとえば、次のAPIがあります。
public interface X<E> {
    E get();
    E set(E e);
}
次に、次のメソッドを宣言するとします。
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());
    }
}
私の「直感的な」理解から、未知のものがクライアントコードに正式に未知であるということを除いて、X<?>実際にはと同じです。しかし、の内部では、コンパイラーが(疑似JLSコード)を推測できると思います。これは、ほとんどのプログラマーが明示的かつ直感的に行うことです。彼らはプライベートヘルパーメソッドに委任します。これは多くの役に立たないボイラープレートコードにつながります。X<T><T>foo()<T0> := <?>[0], <T1> := <?>[1], etc...
public class Foo {
    public void foo(X<?> x) {
        foo0(x);
    }
    private <T> void foo0(X<T> x) {
        x.set(x.get());
    }
}
もう一つの例:
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());
    }
}
つまり、コンパイラは、のワイルドカードx.set()が形式的にはのワイルドカードと同じであることを認識していx.get()ます。なぜその情報を使用できないのですか?JLSには、この不足しているコンパイラの「機能」を説明する形式的な側面がありますか?