Является ли переключатель со строками больше, чем просто синтаксическим сахаром?

Так как Java 1.7, строки могут использоваться с операторами switch, что заставляет меня задуматься. Операторы switch для целочисленных значений превращаются в таблицы перехода, которые быстрее, чем просто выполнение if проверок целых чисел, вычисляемых во время выполнения; может ли подобная оптимизация быть выполнена со строками или это просто синтаксический сахар?

Ответ 1

Да, переключатель со строкой - это синтаксический сахар. Из здесь

1) Строки в Switch - это синтаксический сахар, без изменения уровня JVM.

2) Внутри он использует метод equals для сравнения, что означает, если вы передать null, он будет вызывать java.lang.NullPointerException, поэтому остерегайтесь что.

3) Строки в операторах switch чувствительны к регистру, предпочитают использовать только один случай и преобразовать ввод в предпочтительный случай, прежде чем передавать их switch.

Также проверьте Как работает String в Switch в Java 7

Из той же ссылки, если вы видите пример:

public class StringInSwitchCase{ 
    public static void main(String[] args) { 
        String mode = args[0]; switch (mode) { 
            case "ACTIVE": System.out.println("Application is running on Active mode"); 
                break; 
            case "PASSIVE": System.out.println("Application is running on Passive mode"); 
                break; 
           case "SAFE": System.out.println("Application is running on Safe mode"); 
        } } }

и декомпилированный код:

import java.io.PrintStream; 
public class StringInSwitchCase{ 
    public StringInSwitchCase() { } 
    public static void main(string args[]) { 
        String mode = args[0]; String s; 
        switch ((s = mode).hashCode()) { 
            default: break; 
            case -74056953: if (s.equals("PASSIVE")) { 
                System.out.println("Application is running on Passive mode"); } 
                break; 
            case 2537357: if (s.equals("SAFE")) { System.out.println("Application is running on Safe mode"); }
                break; 
            case 1925346054: if (s.equals("ACTIVE")) { System.out.println("Application is running on Active mode"); } 
                break; } } }

вы узнаете, что String в Switch работает с помощью методов hashCode() и equals().

Как и ожидалось, он использует метод hashCode() для переключения и equals() метод проверки, это означает, что это просто синтаксический сахар, а не встроенные встроенные функции.

Ответ 2

Компилятор оптимизирует оператор switch на основе строковых значений, используя метод hashCode(), а затем использует таблицу поиска в байте-коде. Это обычно более эффективно, чем оператор if - else.

Например, следующее:

String string = "x";
switch(string) {
    case "x": System.out.println("x");
              break;
    case "y": System.out.println("y");
              break;
    case "z": System.out.println("z");
              break;
}

преобразуется в этот байт-код:

ldc "x"
astore_1
aload_1
astore_2
iconst_m1
istore_3
aload_2
invokevirtual java/lang/String/hashCode()I
tableswitch 120
  10
  17
  24
  default: 30
aload_2
ldc "x"
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z
ifeq 30
iconst_0
istore_3
goto 30
aload_2
ldc "y"
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z
ifeq 30
iconst_1
istore_3
goto 30
aload_2
ldc "z"
invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z
ifeq 30
iconst_2
istore_3
iload_3
tableswitch 0
  32
  36
  40
  default: 43
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "x"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
goto 43
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "y"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
goto 43
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "z"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
return