IMLC.ME

Shall I avoid Exclamation Mark(!) in If-Statement in Java

Today I read a post that we should not use "!" in If statement in order to gain a better Perfermance. Because the "!" operator adds extra action for your program. It sounds not a good idea. Is it really truth?

I did a simple experiment.

I wrote 2 Java snippets:

// App.java
public final class App {
        public static void main(String[] args) {
                if(App.shouldPrintMessage()) {
                        System.out.println("Hello, wolrd");
                }
        }

        public static boolean shouldPrintMessage() {
                return true;
        }
}

Ran javac App.java and then I got App.class. Ran javap -c App.class to view the bytecode.

Here it is:

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

  public static void main(java.lang.String[]);
    Code:
       0: invokestatic  #2                  // Method shouldPrintMessage:()Z
       3: ifeq          14                  // If-Equal !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       6: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       9: ldc           #4                  // String Hello, wolrd
      11: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      14: return

  public static boolean shouldPrintMessage();
    Code:
       0: iconst_1
       1: ireturn
}

And then I added ! in If-Statement

public final class App {
        public static void main(String[] args) {
                if(!App.shouldPrintMessage()) {
                        System.out.println("Hello, wolrd");
                }
        }

        public static boolean shouldPrintMessage() {
                return true;
        }
}

Checked the bytecode

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

  public static void main(java.lang.String[]);
    Code:
       0: invokestatic  #2                  // Method shouldPrintMessage:()Z
       3: ifne          14                  // If-Not-Equal !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       6: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       9: ldc           #4                  // String Hello, wolrd
      11: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      14: return

  public static boolean shouldPrintMessage();
    Code:
       0: iconst_1
       1: ireturn
}

As you can see, the main difference is the ifeq and the ifne.


Let me tried the example exactly provided in the post I read.


public final class App {
	public static void main(String[] args) {
		int a = 2;
		if(!(a <= 1)) {
			System.out.println("Hello, wolrd");
		}
	}

}

// vs

public final class App {
	public static void main(String[] args) {
		int a = 2;
		if(a > 1) {
			System.out.println("Hello, wolrd");
		}
	}
}

And here is the output

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

  public static void main(java.lang.String[]);
    Code:
       0: iconst_2
       1: istore_1
       2: iload_1
       3: iconst_1
       4: if_icmple     15
       7: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      10: ldc           #3                  // String Hello, wolrd
      12: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      15: return
}

// vs

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

  public static void main(java.lang.String[]);
    Code:
       0: iconst_2
       1: istore_1
       2: iload_1
       3: iconst_1
       4: if_icmple     15
       7: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      10: ldc           #3                  // String Hello, wolrd
      12: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      15: return
}

They're exactly the same in bytecode level.

Two examples showed us that there is NO addtional operation even though we use "!" in If-Statement. And futhermore, don't forget we have runtime optimazation in Java. In 2019, I quite believe the JVM is smart enough to resolve this problem. So I think we can choose whatever we want in If-Statement from the readability perspective.