Angesichts der folgenden zwei Klassendefinitionen:Parametrierung Nun Geformt und Capture-Konvertierung in Java
class C1<T extends C1<T>> {}
class C2<U> extends C1<C2<U>> {}
und die folgende Typdeklaration:
C1<C2<?>> a;
Intuitiv fühlt es sich an den deklarierten Typ a
gültig sein sollte, aber Dies ist nicht die Art, wie JDK-8u45 sich verhält. Stattdessen bekommen wir so etwas wie die folgende Ausgabe:
Test.java:3: error: type argument C2<?> is not within bounds of type-variable T
C1<C2<?>> a;
^
where T is a type-variable:
T extends C1<T> declared in class C1
1 error
(Edit: Ich war hier schon ein dingus zu sein, hat dieser Teil beantwortet: C2<?>
nicht C1<C2<?>>
erstrecken sich die Frage in Bezug auf die Erklärung von c
unten. obwohl es noch eine offene Frage.)
Aber C2<?>
hatC1<C2<?>>
zu erweitern, die belanglos erscheinen würde, um die gebundene zu befriedigen. Die Untersuchung der JLS liefert keine weitere Beleuchtung soweit ich sehen kann. Es sollte nur so einfach sein, wie die Bindung durch die Subtyprelation zu erfüllen, da kein Platzhalter ist und daher Capture-Konvertierung nur eine Identitätskonvertierung für das Argument ist.
Es gibt Situationen, in denen es etwas weniger klar wird, zum Beispiel, nehmen Sie die folgenden Klassendefinitionen:
class C3<T extends C3<?>> {}
class C4<Y, Z> extends C3<C4<Z, Y>> {}
class C5<X extends C3<X>> {
void accept(X x);
}
Das alles ist in Ordnung, aber dann, wenn wir versuchen, die folgende Erklärung ab:
C5<C6<?, ?>> b;
Dinge werden fremd. C6<?, ?>
ist ein Untertyp von C3<C6<?, ?>>
, daher sollte die Deklaration gemäß meiner Interpretation der oben angegebenen Spezifikation bezüglich der Deklaration C1<C2<?>>
gültig sein. Das Problem ist, dass offensichtlich nicht alle möglichen Subtyp von C6<?, ?>
genügen tatsächlich, dass gebunden, so dass nun zum Beispiel C5.accept()
seinen Parametertyp C6<?, ?>
löst und so Argumente, die den Begrenzungs auf X
verletzen können annehmen, dh jeder, wo die Parametrisierungen Y
und Z
sind nicht identisch.
Wohin gehe ich hier falsch? Ist mein Verständnis der Subtypbeziehung nicht ausreichend?
(Edit: Der folgende Teil der Frage ist noch unbeantwortet, aber ich habe es auf eine neue Frage here bewegt, da es sich um eine ganz andere Frage ist wirklich ... Sorry für ein Chaos und nicht mit der Website sehr gut haha ...)
Abgesehen davon habe ich auch einige Probleme mit Capture-Konvertierung in ähnlichen Situationen. Nehmen Sie die folgende Typdeklaration:
C1<? extends C2<?>> c;
Im Gegensatz zu der gleichlautende Erklärung a
am Start, kompiliert diese Fein in JDK-8u45. Wenn wir jedoch die specification for capture conversion untersuchen, scheint es, dass diese Deklaration zu einem Kompilierungsfehler diesmal führen sollte.
Insbesondere ist die obere Grenze des neuen Typs variable capture CAP#T
von glb(Bi, Ui[A1:=S1,...,An:=Sn])
gegeben, wobei in diesem Fall löst Bi
zu den Platzhalter gebunden C2<?>
und Ui[A1:=S1,...,An:=Sn]
zu C1<CAP#T>
lösen.
Daraus löst glb(C2<?>, C1<CAP#T>)
an der Kreuzung Typ C2<?> & C1<CAP#T>
, die ungültig ist, weil C2<?>
und C1<CAP#T>
beide Klassentypen sind, nicht Typen Schnittstelle, aber keiner von ihnen ist ein Subtyp des anderen.
Diese (scheinbare) Regelverletzung wird in der definition of the intersection type selbst deutlicher gemacht.
Ich bin sicher, es ist kein Fehler und ich mache nur ein paar einfache Fehler irgendwo ... aber wenn hier niemand etwas für mich herausfinden kann, werde ich die Compiler-Dev-Mailingliste oder so etwas ausprobieren.
Danke für jede Hilfe!
Es ist ein faszinierendes Thema. Ich bin nur neugierig, ist das ein theoretisches Problem, oder hast du echte Klassen? Ich kann mir einfach nicht vorstellen, wo man 'Klasse C1> {}' oder 'Klasse C2 erweitert C1 > {}' verwenden würde. –
Kris
Gültige Frage! Ich habe keine spezielle Anwendung dieses speziellen Problems in der realen Welt ... Aber ich * muss * das richtige erwartete Verhalten verstehen, da ich eine Reihe von reflektiven Dienstprogrammen über das Typsystem schreibe und möchte, dass das Verhalten der Spezifikation entspricht. JDK. Momentan funktioniert es meistens, einschließlich der Typinferenz des generischen Methodenaufrufs, aber es gibt einige Randfälle (wie diese), die Probleme verursachen. Wenn Sie einen Blick darauf werfen möchten, ist es hier gehostet: https://github.com/StrangeSkies/uk.co.strangeskies. Noch kein Wiki, aber die Javadocs sind alle für das Paket ".reflection" vorhanden. –
Das hat eigentlich wenig mit Capture-Konvertierung zu tun. Stattdessen sollten Sie in 4.10.2 und 4.5.1 nach Antworten suchen. Sie werden in die Irre geführt, solange Sie dies als mit der Capture-Konvertierung verbunden betrachten. Zum Beispiel, Ihre Begründung dafür, warum 'C1 erweitert C2 >> 'sollte nicht Kompilieren ist Unsinn. (Ich denke, es ist auch falsch, ich glaube nicht, dass es einen Schnittstellentyp gibt, wenn die Capture-Konvertierung * angewendet wurde, weil [Capture-Konvertierung nicht rekursiv angewendet wird]) (http://stackoverflow.com/a/30385343/2891664) aber ich bin gerade aufgewacht, also bin ich ein bisschen benommen.) – Radiodef