2014-07-17 8 views
5

Ho letto spesso che i caratteri jolly Java sono un concetto più potente del concetto di varianza del sito d'uso. Ma a mio avviso, il concetto di jolly Java è esattamente uguale a il concetto di varianza del sito di utilizzo.Perché i caratteri jolly Java sono più potenti della varianza del sito di utilizzo?

Quindi qual è la differenza tra i due? Puoi dare un esempio concreto che è possibile con i jolly Java, ma non con l'uso della varianza del sito?

Per esempio, la prima risposta in How does Java's use-site variance compare to C#'s declaration site variance? è un esempio in cui è fornita l'indicazione della mia domanda:

Prima di tutto, se non ricordo male usare loco varianza è strettamente più potente di declaration- varianza del sito (sebbene al costo della concisione ), o almeno i caratteri jolly di Java sono (che sono in realtà più potenti della varianza del sito di utilizzo).

Tuttavia, la risposta non indica qual è la differenza, solo che ce n'è uno.

Edit: Una prima differenza che ho trovato here (primo paragrafo a pagina 112) sembra essere che l'uso in loco varianza non consente completamente chiamando un metodo che ha un parametro di tipo nella posizione sbagliata, mentre i caratteri jolly consentono definendolo con alcuni tipi. Ad esempio, non è possibile chiamare add, su un List<? extends String>. Con caratteri jolly Java, è possibile chiamata add su una tale classe, ma è necessario utilizzare null come argument.For controvarianza, uno può chiamata di un metodo che restituisce un parametro controvariante ma si deve presumere che il tipo di ritorno è Object . Ma questa è l'unica differenza?

+0

È diverso da questa domanda? http://stackoverflow.com/questions/4231305/how-does-javas-use-site-variance-compare-to-cs-declaration-site-variance –

+1

@IsaiahvanderElst: No, la domanda che hai collegato riguarda il sito di dichiarazione varianza (ad es., C# 'out') vs. usa la varianza del sito. La mia domanda riguarda l'uso della varianza del sito rispetto ai caratteri jolly che sembrano essere esattamente gli stessi per me. Ma la prima risposta nella domanda che hai collegato dichiara almeno la mia affermazione: "o almeno i caratteri jolly di Java sono (che sono in realtà più potenti della varianza del sito di utilizzo)" – gexicide

+0

@IsaiahvanderElst: ho espresso in modo errato la prima frase del mio commento precedente. Quello che volevo dire era "** Sì **, questa domanda è completamente diversa da quella che hai collegato". Spero che sia chiaro nella spiegazione. – gexicide

risposta

5

Dopo aver letto molto su questo argomento, mi sembra di aver trovato una risposta nel documento this di Altidor, Reichenbach e Smaragdakis. L'aggiunta principale che i generici Java hanno in contrasto con la varianza del sito d'uso è la conversione di cattura che consente di catturare il tipo precedentemente sconosciuto di un carattere jolly in un parametro di tipo. Questo esempio dalla carta lo spiega meglio:

Una complicazione è che i caratteri jolly Java non sono semplicemente utilizzare loco varianza, ma includono anche i meccanismi ispirati alla esistenziali digitando meccanismi. L'acquisizione di caratteri jolly è il processo di passaggio di un tipo sconosciuto , nascosto da un carattere jolly, come parametro di tipo in un metodo di chiamata . Si consideri il seguente metodo, che scambia l'ordine con lo due elementi nella parte superiore di uno stack.

<E> void swapLastTwo(Stack<E> stack) { 
     E elem1 = stack.pop(); 
     E elem2 = stack.pop(); 
     stack.push(elem2); 
     stack.push(elem1); 
    } 

Anche se un programmatore può decidere di passare un oggetto di tipo Stack<?> come argomento valore al metodo di swapLastTwo, il parametro di tipo da passare per E non può essere speci manualmente fi cato perché il tipo di nascosto da ? non può essere nominato dal programmatore. Tuttavia, il superamento di un controllo di tipo perché Java consente al compilatore di generare automaticamente un nome per il tipo sconosciuto (conversione di acquisizione) e utilizzare questo nome in un metodo invocazione.

cioè in Java, si può chiamare swapLastTwo() utilizzando un argomento di input Stack<?> come. Il compilatore quindi acquisisce ? nella variabile di tipo E e quindi sa che possiamo chiamare push sugli elementi che abbiamo appena pop ed. Con la varianza del sito di utilizzo, non è stato possibile farlo poiché il sistema di tipi avrebbe perso le informazioni che l'elemento restituito da pop è del tipo che push anticipa.

Si noti che è necessario utilizzare un parametro di tipo per acquisire il tipo. In caso contrario, il type checker considererà il tipo restituito da pop in modo diverso rispetto al tipo previsto da push.

Ad esempio, questo non viene compilato in Java:

Stack<?> s = ...; 
s.push(s.pop()); 

Qui, il tipo di elemento di s saranno catturati in due diverse variabili di tipo fresco (chiamati capture 1 of ? e capture 2 of ? in Eclipse il tipo di correttore tratta. queste variabili di tipo diverso come e il codice non viene compilato. utilizzando un metodo generico che può catturare il tipo di ? in un parametro denominato che permette di chiamare e pushpop.

non sono sicuro se questo è l'onl la differenza tra i jolly Java e la "usuale" (qualunque cosa sia) varianza del sito di utilizzo, ma almeno sembra essere una differenza notevole.

Problemi correlati