if(a&&b) 是否应该比 if(a) if(b) 花费更多时间?

Should if(a&&b) take more time than if(a) if(b)?

我使用以下简单逻辑来回答 question 像这样的问题:

1:   if(a)        // 1 operation
2:   if (b)       // 1 operation

1:  if(a && b) // 1, 1(&&), 1 => 3 operations. 

因此,2 个操作与 3 个操作相比,但在第一个示例中,编译器需要调用另一条指令来执行。

这个逻辑对吗?。 它取决于编译器吗? 仅调用 ; 之类的空指令是否会使编译器花费一些明显的时间?

This 也讨论了同样的问题,但没有考虑这个逻辑。 请帮助我们澄清这个问题。

有两种方法可以准确回答这样的问题:

1.) 查看 IL 代码 (and/or) 汇编代码生成并计算执行此代码所需的 CPU 周期(提示:这不适合初学者)

2.) 构建一个小的测试程序,它会多次执行这两种变体,使用 StopWatch() 创建一个有用且可读的计时输出,运行 多次。

3.) 猜猜你认为编译器的优化步骤能做什么,这个软件会做什么,和别人争论几个小时

有两种方法可以考虑您的问题:

  1. Java 语言定义

    • 语言定义第二个示例将使用短路执行,这意味着 if 语句将包含任何代码的情况下,第二个示例可能执行得更快
  2. JVM优化

    • JVM 运行时将删除死代码块,如果它可以证明它们没有任何副作用

我假设编译器会为您的两种情况生成相同的字节码。所以我用两个不同的源文件测试了这个:

public class Test1 {    
  public static void main(String[] args) {
    if (args[0].equals("a"))
      if (args[1].equals("b"))
        System.out.println("Foo");
  }    
}

和...

public class Test2 {    
  public static void main(String[] args) {
    if (args[0].equals("a") && args[1].equals("b"))
      System.out.println("Foo");
  }    
}

javap -c Test1等检查他们的字节码,结果是一样的:

  public static void main(java.lang.String[]);
    Code:
       0: aload_0
       1: iconst_0
       2: aaload
       3: ldc           #2                  // String a
       5: invokevirtual #3                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
       8: ifeq          30
      11: aload_0
      12: iconst_1
      13: aaload
      14: ldc           #4                  // String b
      16: invokevirtual #3                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      19: ifeq          30
      22: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      25: ldc           #6                  // String Foo
      27: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      30: return

因此,性能将是相同的。如果有人能想到生成不同字节码的示例,我欢迎发表评论。

我的结果使用的是来自 Java 1.7 的 Oracle javac。结果可能与其他编译器不同,但我怀疑它们不会适用于这种情况。