Inspired by this question I started out on a little research.
I was able to determine that using primitives, the prefix ++i
just gets rewritten to i++
by the compiler:
Before:
public class PrefixIncrement {
public static void main(String args[]) {
for(Integer i = 0; i < 100; ++i) {
System.out.println(i);
}
}
}
Decompiled with jd-gui 0.36:
import java.io.PrintStream;
public class PrefixIncrement
{
public static void main(String[] args)
{
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
}
}
Okay. So that part was answered. But then I stumbled across what happens when we use the Integer class instead, this time with Postfix:
Before:
public class PostfixIncrement {
public static void main(String args[]) {
for( Integer i = 0; i < 100; i++) {
System.out.println(i);
}
}
}
After decompilation:
import java.io.PrintStream;
public class PostfixIncrement
{
public static void main(String[] args)
{
Integer localInteger1;
Integer localInteger2;
for (Integer i = Integer.valueOf(0); i.intValue() < 100; localInteger2 = i = Integer.valueOf(i.intValue() + 1))
{
System.out.println(i);localInteger1 = i;
}
}
}
The compiler seems to do some stupid stuff with “i++.” It creates two new integer classes and creates a logically unnecessary series of assignments:
localInteger2 = i = Integer.valueOf(i.intValue() + 1);
localInteger1
doesn’t appear to ever be used. Its just allocated on the stack. Why is javac doing this?
$ java -version
java version "1.7.0_60"
Java(TM) SE Runtime Environment (build 1.7.0_60-b19)
Java HotSpot(TM) 64-Bit Server VM (build 24.60-b09, mixed mode)
===================BY REQUEST: javap output=======================
Postfix Increment using the Integer
class.
{
public com.foo.PostfixIncrement();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>
":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/matt/PostfixIncrement;
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: iconst_0
1: invokestatic #2 // Method java/lang/Integer.valueO
f:(I)Ljava/lang/Integer;
4: astore_1
5: aload_1
6: invokevirtual #3 // Method java/lang/Integer.intVal
ue:()I
9: bipush 100
11: if_icmpge 40
14: getstatic #4 // Field java/lang/System.out:Ljav
a/io/PrintStream;
17: aload_1
18: invokevirtual #5 // Method java/io/PrintStream.prin
tln:(Ljava/lang/Object;)V
21: aload_1
22: astore_2
23: aload_1
24: invokevirtual #3 // Method java/lang/Integer.intVal
ue:()I
27: iconst_1
28: iadd
29: invokestatic #2 // Method java/lang/Integer.valueO
f:(I)Ljava/lang/Integer;
32: dup
33: astore_1
34: astore_3
35: aload_2
36: pop
37: goto 5
40: return
LineNumberTable:
line 5: 0
line 6: 14
line 5: 21
line 8: 40
LocalVariableTable:
Start Length Slot Name Signature
5 35 1 i Ljava/lang/Integer;
0 41 0 args [Ljava/lang/String;
StackMapTable: number_of_entries = 2
frame_type = 252 /* append */
offset_delta = 5
locals = [ class java/lang/Integer ]
frame_type = 250 /* chop */
offset_delta = 34
}