Wie legt das JLS fest, dass Platzhalter in Methoden nicht formal verwendet werden können?

Ich habe mich immer über einen seltsamen Aspekt von Java-Generika und die Verwendung von Platzhaltern gewundert. Angenommen, ich habe die folgende API:

public interface X<E> {
    E get();
    E set(E e);
}

Nehmen wir an, wir deklarieren die folgenden Methoden:

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());
    }
}

Nach meinem "intuitiven" VerständnisX<?> ist in der Tat das gleiche wieX<T>, außer dass der Unbekannte<T> istformal Clientcode unbekannt. Aber innerhalb vonfoo(), Ich würde vermuten, dass der Compiler darauf schließen könnte (Pseudo-JLS-Code)<T0> := <?>[0], <T1> := <?>[1], etc.... Dies ist, was die meisten Programmierer explizit und intuitiv tun. Sie delegieren an eine private Helfer-Methode, die zu einer Menge nutzlosem Code auf der Kesselplatte führt:

public class Foo {
    public void foo(X<?> x) {
        foo0(x);
    }

    private <T> void foo0(X<T> x) {
        x.set(x.get());
    }
}

Ein anderes Beispiel:

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());
    }
}

Mit anderen Worten, der Compiler weiß, dass der Platzhalter inx.set() ist formal das Gleiche wie der Platzhalter inx.get(). Warum kann es diese Informationen nicht verwenden? Gibt es einen formalen Aspekt in derJLS, das erklärt dieses fehlende Compiler "Feature"?

Antworten auf die Frage(3)

Ihre Antwort auf die Frage