Java 7: Project Coin

Strings in „switch“-Anweisungen

Bislang konnte man in einer switch-Anweisung nur über Werte eines primitiven oder Enum-Typs verzweigen. In Java 7 darf auch über konstante Strings verzweigt werden [1], [4]. Der Vorteil liegt darin, dass der Compiler aus einem switch über Strings effizienteren Code erzeugen kann, als es mit den bislang zur Verfügung stehenden Sprachmitteln möglich ist. Man darf also in Java 7 so schreiben, wie es in Listing 1 dargestellt wird.

Listing 1: String switch in Java 7
    private static final String IDLE = "idle";

    public static void newStringSwitch(String state) {
        final String terminal = "terminated";

        if (state== null)	
            System.out.println("No state"); 
        switch (state) {
        case "busy":   // fall through works as before
        case terminal: // local final variables are ok
        case IDLE: {   // constants are ok
            System.out.println("Matched state");
            break; }
        default: {
            System.out.println("Unknown state");
            break; }
        }
    }

Im switch wird über eine String-Variable verzweigt, und die case-Labels dürfen String-Literale oder final-String-Variablen sein; non-final-String-Variablen sind als case-Labels nicht erlaubt. Der Effizienzzuwachs rührt daher, dass man mit heutigen Sprachmitteln eine else-if-Kaskade mit equals()-Vergleichen für alle Strings hinschreiben müsste. Eine solche Kaskade kann vom Compiler schlecht optimiert werden. Aus einem switch über Strings kann der Compiler hingegen einen switch über die Hashcodes der Strings machen, was dann nur noch einen einzigen equals()-Aufruf statt einer Sequenz von Methodenaufrufen erfordert. Mit herkömmlichen Mitteln wäre die Verzweigung im obigen Beispiel nur mit einer if-else-Kaskade möglich gewesen, in der der variable String state sukzessive mit allen konstanten Strings verglichen wird, bis eine Übereinstimmung gefunden wird. Das hätte etwa wie in Listing 2 ausgesehen.

Listing 2: Herkömmliche Verzweigung über Strings (in Java 6)
    public static void classicStringSwitch(String state) {
        System.out.println("OLD ...");
        final String terminal = "terminated";
        if (state== null)
            System.out.println("No state"); 
        else if (state.equals("busy") || state.equals(terminal) || 
                               state.equals(IDLE))
            System.out.println("Matched state");
        else 
            System.out.println("Unknown state");// default
    }

Die vielen Vergleiche mit String.equals() sind ineffizient. Die Implementierung des neuen Strings switch eliminiert den Overhead, indem sie erst über die Hashcodes der String verzweigt und danach (bei Bedarf) noch den Vergleich per String.equals() nutzt. Das heißt, nachdem der Compiler den String switch in Bytecode übersetzt hat, sieht die Verzweigung sinngemäß wie in Listing 3 aus. Der neue String switch ist also nicht nur übersichtlicher, sondern auch noch effizienter.

Listing 3: Das Bytecode-Äquivalent des Strings switch (in Java 7)
    public static void newStringSwitch(String state) {
        if(s == null)
            System.out.println("No state");
        String s1 = state;
        byte byte0 = -1;
        switch(s1.hashCode())
        {
        case 3035641: 
            if(s1.equals("busy"))
                byte0 = 0;
            break;

        case -1308815837: 
            if(s1.equals("terminated"))
                byte0 = 1;
            break;

        case 3227604: 
            if(s1.equals("idle"))
                byte0 = 2;
            break;
        }
        switch(byte0)
        {
        case 0: 
        case 1: 
        case 2: 
            System.out.println("Matched state");
            break;

        default:
            System.out.println("Unknown state");
            break;
        }
    }
Zusammenfassung

In diesem Beitrag haben wir einige der neuen Sprachmittel aus dem Project Coin betrachtet. Die verbesserten Notationen für numerische Literale sind so naheliegend, dass man sich fragt, warum es sie nicht schon immer gegeben hat. Strings in switch-Anweisungen sorgen für bessere Lesbarkeit des Codes und sind zudem auch noch effizienter als die herkömmlichen Sprachmittel.

In den nächsten Beiträgen sehen wir uns die weiteren Project Coin Features an: Verbessertes Exception Handling, Automatic Resource Management, Methoden mit variabler Argumentenliste und die sogenannten Diamond Operatoren.

Angelika Langer arbeitet selbstständig als Trainer mit einem eigenen Curriculum von Java- und C++-Kursen. Kontakt: http://www.AngelikaLanger.com.

Klaus Kreft arbeitet als Entwickler und Consultant, derzeit für SEN (Siemens Enterprise Communications GmbH & Co. KG). Kontakt: klaus.kreft[at]siemens-enterprise.com.

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.