Java Operators – Difference Between Prefix and Postfix ++

bytecodejavajvmoperators

There are a few questions regarding this (like Java: Prefix/postfix of increment/decrement operators?) but I'm not asking about the general difference between postfix and prefix ++ operators (I know that part), but about the fundamental difference between them at the Java specification level.

Specifically, is there any difference between prefix and postfix ++ operators other than operator precedence (maybe in the way the javac translates the commands to bytecode or in the way the JVM runs that bytecode)?

For example, would the following code necessarily run the same (in every JVM):

for (int i = 0; i < X; i++) { ... }

And

for (int i = 0; i < X; ++i) { ... }

Is there anything in the JLS that defines that these 2 statements would run in exactly the same way on every platform, Java compiler, JVM, etc., or is it possible (even theoretically) that these 2 statements will run differently?

Best Answer

Yes, it would run the same. It would compile to the same bytecode, thus JVM will notice no difference whatever JVM it is.

You may check it by yourself:

public class TestIncrement {
    public void testPost(int X) {
        for (int i = 0; i < X; i++) {
            System.out.println(i);
        }
    }

    public void testPre(int X) {
        for (int i = 0; i < X; ++i) {
            System.out.println(i);
        }
    }
}

Both methods are compiled in the same way using either JavaC compiler:

public void testPost(int);
Code:
   0: iconst_0
   1: istore_2
   2: iload_2
   3: iload_1
   4: if_icmpge     20
   7: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
  10: iload_2
  11: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
  14: iinc          2, 1
  17: goto          2
  20: return

Or ECJ compiler:

public void testPost(int);
Code:
  0: iconst_0
  1: istore_2
  2: goto          15
  5: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
  8: iload_2
  9: invokevirtual #22                 // Method java/io/PrintStream.println:(I)V
 12: iinc          2, 1
 15: iload_2
 16: iload_1
 17: if_icmplt     5
 20: return

Different compilers generate different bytecode, but in both cases the bytecode is the same for both methods.

Related Question