当前位置: 首页 > 面试题库 >

为什么在Java 7中switch语句比String语句要快?

卢志行
2023-03-14
问题内容

Java 7中
string对象可以位于switch语句的表达式中。有人可以从官方文档中解释以下声明吗?

与使用链式if-then-else语句相比,Java编译器通常从使用 String对象的 switch语句生成更有效的字节码。


问题答案:

Java代码

具有一个类的两个版本,例如

if-then-else

public class IfThenElseClass {
    public static void main(String[] args) {
        String str = "C";
        if ("A".equals(str)) {

        } else if ("B".equals(str)) {

        } else if ("C".equals(str)) {

        }
    }
}

switch

public class SwitchClass {
    public static void main(String[] args) {
        String str = "C";
        switch (str) {
            case "A":
                break;
            case "B":
                break;
            case "C":
                break;
        }
    }
}

字节码

让我们看一下字节码。获取if-then-else版本的字节码:

Compiled from "CompileSwitch.java"
public class CompileSwitch {
  public CompileSwitch();
    Code:
       0: aload_0
       1: invokespecial #8  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #16 // String C
       2: astore_1
       3: ldc           #18 // String A
       5: aload_1
       6: invokevirtual #20 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
       9: ifne          28
      12: ldc           #26 // String B
      14: aload_1
      15: invokevirtual #20 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      18: ifne          28
      21: ldc           #16 // String C
      23: aload_1
      24: invokevirtual #20 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      27: pop
      28: return
}

获取switch版本的字节码:

Compiled from "CompileSwitch.java"
public class CompileSwitch {
  public CompileSwitch();
    Code:
       0: aload_0
       1: invokespecial #8 // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #16 // String C
       2: astore_1
       3: aload_1
       4: dup
       5: astore_2
       6: invokevirtual #18 // Method java/lang/String.hashCode:()I
       9: lookupswitch  { // 3
                    65: 44
                    66: 56
                    67: 68
               default: 77
          }
      44: aload_2
      45: ldc           #24 // String A
      47: invokevirtual #26 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      50: ifne          77
      53: goto          77
      56: aload_2
      57: ldc           #30 // String B
      59: invokevirtual #26 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      62: ifne          77
      65: goto          77
      68: aload_2
      69: ldc           #16 // String C
      71: invokevirtual #26 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      74: ifne          77
      77: return
}

结论

  • 在第一个版本中,通过equals为每个条件调用方法来比较字符串,直到找到为止。

  • 在第二个版本中,首先hashCode获取字符串。然后,这是与值hashCode的每个case。请参阅lookupswitch。如果重复这些值中的任何一个,则恰好为该代码运行代码case。否则,调用equals捆绑方法的情况。这比equals仅调用该方法快得多。



 类似资料:
  • switch 语句可以替代多个 if 判断。 switch 语句为多分支选择的情况提供了一个更具描述性的方式。 语法 switch 语句有至少一个 case 代码块和一个可选的 default 代码块。 就像这样: switch(x) { case 'value1': // if (x === 'value1') ... [break] case 'value2':

  •  使用 switch 语句可以更简洁地实现 if ~ else if 的结构。格式如下。 switch(base_expression) { casecondition_expression1: casecondition_expression2: : : default: : : }  写在 base_expression 位置的表达式会在刚开始时被求值。switch 后面的语句块中的 case

  • 问题内容: 我只是想知道为什么Java 7 语句不支持大小写而是抛出?请参见下面的注释行(示例摘自上的Java教程文章): 这样可以避免每次使用前都进行空检查的条件。 问题答案: 正如damryfbfnetsi 在评论中指出的那样,JLS§14.11具有以下注释: 禁止将其用作开关标签,以防止他人编写永远无法执行的代码。如果表达式是引用类型,即装箱的原始类型或枚举类型,则如果表达式在运行时求值为,

  • 问题内容: 我有一个问题,我需要查找具有与值匹配的度量 或 根本没有该度量的记录。我使用s,using和using三种或四种不同的方法解决了该问题。但是,每次查询最终都变得非常慢。然后,我尝试将查询一分为二,它们都非常快地运行(三秒钟)。但是使用组合查询需要花费超过五分钟的时间。 在SO上阅读,我尝试了,速度非常快,但是对于我正在使用的脚本非常不便。 有两个问题: 为什么这么快?(或者为什么这么慢

  • rank ▲ ✰ vote url 62 370 162 300 url Python中用什么代替switch语句? 我想写一个函数,实现输入一个值对应输出另一个值. 在其他语言我可以用switch或者case语句,但是Python里没有switch.Python里如何解决这个问题? 你可以用一个字典: def f(x): return { 'a': 1,

  • C# 中的 switch 语句有些类似于《 if else if 语句》,都可以根据表达式执行某个的语句块,其语法格式如下: switch(表达式){     case value1:     //表达式的值为 value1 时,要执行的代码         break;     case value2:     //表达式的值为 value2 时,要执行的代码         break;