Le istruzioni switch con String
casi sono state implementate in Java SE 7 , almeno 16 anni dopo la loro richiesta. Non è stato fornito un chiaro motivo del ritardo, ma probabilmente ha avuto a che fare con le prestazioni.
Implementazione in JDK 7
La funzionalità è stata ora implementata javac
con un processo di "riduzione dello zucchero"; una sintassi pulita e di alto livello che utilizza le String
costanti nelle case
dichiarazioni viene espansa in fase di compilazione in codice più complesso seguendo uno schema. Il codice risultante utilizza le istruzioni JVM che sono sempre esistite.
Un caso switch
con String
viene tradotto in due interruttori durante la compilazione. La prima mappa ogni stringa su un numero intero univoco, ovvero la sua posizione nell'interruttore originale. Questo viene fatto accendendo prima il codice hash dell'etichetta. Il caso corrispondente è if
un'istruzione che verifica l'uguaglianza delle stringhe; se ci sono collisioni sull'hash, il test è a cascata if-else-if
. Il secondo interruttore rispecchia quello nel codice sorgente originale, ma sostituisce le etichette del caso con le posizioni corrispondenti. Questo processo in due passaggi semplifica la conservazione del controllo del flusso dell'interruttore originale.
Passa alla JVM
Per ulteriori approfondimenti tecnici switch
, è possibile fare riferimento alla specifica JVM, in cui è descritta la compilazione delle istruzioni switch . In breve, ci sono due diverse istruzioni JVM che possono essere utilizzate per un interruttore, a seconda della scarsità delle costanti utilizzate dai casi. Entrambi dipendono dall'utilizzo di costanti intere per ciascun caso per l'esecuzione efficiente.
Se le costanti sono dense, vengono utilizzate come indice (dopo aver sottratto il valore più basso) in una tabella di puntatori di istruzioni: l' tableswitch
istruzione.
Se le costanti sono sparse, viene eseguita una ricerca binaria per il caso corretto: l' lookupswitch
istruzione.
In de-zuccheraggio una switch
su String
oggetti, entrambe le istruzioni sono suscettibili di essere utilizzati. Il lookupswitch
è adatto per la prima accensione codici hash per trovare la posizione originaria del caso. L'ordinale risultante è una misura naturale per a tableswitch
.
Entrambe le istruzioni richiedono che le costanti intere assegnate a ciascun caso siano ordinate al momento della compilazione. In fase di esecuzione, sebbene le O(1)
prestazioni di tableswitch
generalmente appaiano migliori delle O(log(n))
prestazioni di lookupswitch
, sono necessarie alcune analisi per determinare se la tabella è abbastanza densa da giustificare il compromesso spazio-tempo. Bill Venners ha scritto un ottimo articolo che lo tratta in modo più dettagliato, insieme a uno sguardo nascosto ad altre istruzioni di controllo del flusso Java.
Prima di JDK 7
Prima di JDK 7, enum
poteva approssimare un String
interruttore basato su. Questo utilizza ilvalueOf
metodo statico generato dal compilatore su ogni enum
tipo. Per esempio:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}