terça-feira, março 09, 2010

Switch com Strings no Java 7

Uma coisa que existe em quase todas as linguagens, exceto Java e C++, é a facilidade de você usar um "switch" com o tipo String. Isso será adicionado ao Java 7.
Peço permissão ao Entanglement para postar um programa que ele mostrou no GUJ:
class TesteSwitch {
    public static void main (String[] args) {
        String s = "desprezível";
        switch (s) {
        case "desprezível":
            System.out.println ("despicable"); break;
        case "auréola":
            System.out.println ("halo"); break;
        case "fungo":
            System.out.println ("fungus"); break;
        case "fujão":
            System.out.println ("fugitive"); break;
        case "abstruso":
            System.out.println ("abstruse"); break;
        }
    }
}
Sendo que esse programa foi transformado pelo compilador para o equivalente a:
class TesteSwitch {
    public static void main (String[] args) {
        String s = "desprezível";
        int hashCode = s.hashCode();
        int i = -1;
        switch (hashCode) {
        case -644512679: if (s.equals ("auréola")) i = 1; 
                         else if (s.equals("desprezível") i = 0; 
                         break;
        case 97793703: if (s.equals ("fujão") i = 3; 
                       else if (s.equals("fungo") i = 2; 
                       break; 
        case 1732918561: if (s.equals ("abstruso") i = 4; 
                         break;
        default: break;
        }
        switch (i) {
        case 0: System.out.println ("despicable"); break;
        case 1: System.out.println ("halo"); break;
        case 2: System.out.println ("fungus"); break;
        case 3: System.out.println ("fugitive"); break;
        case 4: System.out.println ("abstruse"); break;
        }
    }
}

O compilador transforma 1 switch em 2, porque é mais fácil tratar de certos casos (como "fallthrough" e strings que têm exatamente o mesmo hash code). Por exemplo, no caso acima, "auréola" e "desprezível" têm o mesmo hash code, assim como "fujão" e "fungo". E é por isso que o switch checa se o hash code E a string são os mesmos do caso. Se o switch tiver muitos casos, essa implementação é mais rápida que simplesmente ir comparando com "ifs" encadeados.

Obviamente, assim como no caso do "switch" com inteiros, é necessário ver se o seu problema não poderia ser resolvido com hierarquias de classes ou então com enums.