Le istruzioni switch con Stringcasi 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 Stringcostanti nelle casedichiarazioni 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 switchcon Stringviene 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 è ifun'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' tableswitchistruzione.
Se le costanti sono sparse, viene eseguita una ricerca binaria per il caso corretto: l' lookupswitchistruzione.
In de-zuccheraggio una switchsu Stringoggetti, 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 tableswitchgeneralmente 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, enumpoteva approssimare un Stringinterruttore basato su. Questo utilizza ilvalueOf metodo statico generato dal compilatore su ogni enumtipo. Per esempio:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}