Dati i seguenti due definizioni di classe:parametrizzazione Bene formedness cattura di conversione in Java
class C1<T extends C1<T>> {}
class C2<U> extends C1<C2<U>> {}
e la seguente dichiarazione del tipo:
C1<C2<?>> a;
Intuitivamente ci si sente il tipo dichiarato a
dovrebbe essere valida, ma questo non è il modo in cui si comporta JDK-8u45. Invece si ottiene qualcosa di simile al seguente output:
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: Ero essere un dingus qui, questa parte è stato risposto: C2<?>
non estende C1<C2<?>>
Il problema per quanto riguarda la dichiarazione di c
di seguito. è ancora una questione aperta, però.)
Ma C2<?>
fa estende C1<C2<?>>
, che sembrerebbe soddisfare banalmente il limite. L'esame di JLS non fornisce ulteriore illuminazione per quanto posso vedere. Dovrebbe essere semplicemente semplice come soddisfare il limite della relazione sottotipo, dal momento che C2<?>
non è un tipo jolly e quindi la conversione dell'acquisizione è solo una conversione dell'identità sull'argomento.
Ci sono situazioni in cui diventa un po 'meno chiaro, ad esempio, prendere le seguenti definizioni di classe:
class C3<T extends C3<?>> {}
class C4<Y, Z> extends C3<C4<Z, Y>> {}
class C5<X extends C3<X>> {
void accept(X x);
}
Tutto questo va bene, ma poi se cerchiamo la seguente dichiarazione:
C5<C6<?, ?>> b;
Le cose diventano estranee. C6<?, ?>
è un sottotipo di C3<C6<?, ?>>
, pertanto la dichiarazione deve essere valida in base all'interpretazione da parte mia delle specifiche sopra riportate in merito alla dichiarazione C1<C2<?>>
. Il problema è che chiaramente non ogni possibile sottotipo di C6<?, ?>
soddisfa in realtà che limite, così ora per esempio C5.accept()
risolve il suo tipo di parametro C6<?, ?>
e così può accettare argomenti che violano la delimitazione su X
, cioè ogni dove le parametrizzazioni Y
e Z
non sono identici.
Dove sto andando storto qui? La mia comprensione della relazione tra sottotipi è insufficiente?
(Edit: La seguente parte della domanda è ancora senza risposta, ma ho spostato in una nuova domanda here dal momento che è una questione completamente diversa davvero ... Ci scusiamo per fare un pasticcio e che non utilizzano il sito molto bene haha ...)
A parte questo, ho anche qualche problema con la conversione di acquisizione in situazioni simili. Prendiamo il seguente dichiarazione del tipo:
C1<? extends C2<?>> c;
A differenza della dichiarazione simile a
alla partenza, questo compila bene in JDK-8u45. Se esaminiamo lo specification for capture conversion, tuttavia, questa dichiarazione dovrebbe produrre in questo momento.
In particolare, il limite superiore del nuovo tipo di acquisizione variabile CAP#T
è data da glb(Bi, Ui[A1:=S1,...,An:=Sn])
, dove in questo caso Bi
risolve il jolly vincolato C2<?>
e Ui[A1:=S1,...,An:=Sn]
risolve C1<CAP#T>
.
Da questo, glb(C2<?>, C1<CAP#T>)
risolve al tipo intersezione C2<?> & C1<CAP#T>
, che è valido, perché C2<?>
e C1<CAP#T>
sono entrambi tipi di classe, non tipi di interfaccia, ma nessuno di essi è un sottotipo dell'altro.
Questa (apparente) violazione delle regole è resa più chiara nello stesso definition of the intersection type.
Sono sicuro che non è un bug e sto solo facendo alcuni semplici errori da qualche parte ... ma se nessuno qui può far luce su questo per me proverò la mailing list di compilatore-dev o qualcosa del genere.
Grazie per qualsiasi aiuto!
È un problema affascinante. Sono solo curioso, questo è un problema teorico o hai qualche lezione del mondo reale per questo? Non riesco a immaginare dove si dovrebbe usare 'classe C1> {}' o 'classe C2 estende C1 > {}'. –
Kris
Domanda valida! Non ho un'applicazione specifica del mondo reale di questo particolare problema ... Ma io * devo * ho bisogno di capire il comportamento atteso corretto, mentre sto scrivendo una serie di utilità riflessive sul sistema di tipi e voglio che il comportamento corrisponda alle specifiche/JDK. Attualmente funziona principalmente, inclusa l'inferenza di tipo dell'invocazione del metodo generico, ma ci sono un paio di casi limite (come questo) che causano problemi. Se vuoi dare un'occhiata è ospitato qui: https://github.com/StrangeSkies/uk.co.strangeskies. Nessun wiki ancora, ma i javadoc sono tutti presenti per il pacchetto '.reflection'. –
Questo in realtà ha ben poco a che fare con la conversione di acquisizione. Invece, dovresti cercare in 4.10.2 e 4.5.1 per le risposte. Ti stai ingannando finché lo vedi come relativo alla conversione dell'acquisizione. Ad esempio, il tuo ragionamento sul perché 'C1 estende C2 >> 'non dovrebbe essere compilato senza senso. (Penso che sia anche sbagliato, non penso che ci sia un tipo di intersezione se la conversione di acquisizione * fosse * applicata, perché [la conversione di acquisizione non sarebbe stata applicata in modo ricorsivo] (http://stackoverflow.com/a/30385343/2891664) ma mi sono appena svegliato quindi sono un po 'intontito.) – Radiodef