Software Engineering Java
In a programming language syntactic sugar is a convenient syntax/construct which makes things
easier for the programmer.
Java language provides many syntactic constructs. For example consider following Java enum class:
public enum EnumTest {
ElementA, ElementB, ElementC
}
Let's compile above class and analyze compiled bytecode via javap:
D:\java-syntactic-sugar-examples>javac EnumTest.java
D:\java-syntactic-sugar-examples>javap EnumTest
Compiled from "EnumTest.java"
public final class EnumTest extends java.lang.Enum<EnumTest> {
public static final EnumTest ElementA;
public static final EnumTest ElementB;
public static final EnumTest ElementC;
public static EnumTest[] values();
public static EnumTest valueOf(java.lang.String);
static {};
}
The compiler has converted the enum class to a normal Java class extending java.lang.Enum . Each enum element is converted to static final constant of the enclosing class type.
Foreach loop is another example:
public class ForEachLoop {
public static void main(String[] args) {
List<Integer> list = List.of(1, 3, 6, 8, 9);
for (int i : list) {
System.out.println(i);
}
}
}
If we compile above class and analyze the compiled code via javap:
D:\java-syntactic-sugar-examples>javac ForEachLoop.java
D:\java-syntactic-sugar-examples>javap -v ForEachLoop
Classfile /D:/java-syntactic-sugar-examples/src/main/java/ForEachLoop.class
Last modified Oct 2, 2018; size 876 bytes
MD5 checksum 3c591f0e683054877602faac8cc45075
Compiled from "ForEachLoop.java"
public class ForEachLoop
minor version: 0
major version: 55
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #11 // ForEachLoop
super_class: #12 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
#1 = Methodref #12.#24 // java/lang/Object."<init>":()V
#2 = Methodref #7.#25 // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
#3 = InterfaceMethodref #20.#26 // java/util/List.of:(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/List;
#4 = InterfaceMethodref #20.#27 // java/util/List.iterator:()Ljava/util/Iterator;
#5 = InterfaceMethodref #21.#28 // java/util/Iterator.hasNext:()Z
#6 = InterfaceMethodref #21.#29 // java/util/Iterator.next:()Ljava/lang/Object;
#7 = Class #30 // java/lang/Integer
#8 = Methodref #7.#31 // java/lang/Integer.intValue:()I
#9 = Fieldref #32.#33 // java/lang/System.out:Ljava/io/PrintStream;
#10 = Methodref #34.#35 // java/io/PrintStream.println:(I)V
#11 = Class #36 // ForEachLoop
#12 = Class #37 // java/lang/Object
#13 = Utf8 <init>
#14 = Utf8 ()V
#15 = Utf8 Code
#16 = Utf8 LineNumberTable
#17 = Utf8 main
#18 = Utf8 ([Ljava/lang/String;)V
#19 = Utf8 StackMapTable
#20 = Class #38 // java/util/List
#21 = Class #39 // java/util/Iterator
#22 = Utf8 SourceFile
#23 = Utf8 ForEachLoop.java
#24 = NameAndType #13:#14 // "<init>":()V
#25 = NameAndType #40:#41 // valueOf:(I)Ljava/lang/Integer;
#26 = NameAndType #42:#43 // of:(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/List;
#27 = NameAndType #44:#45 // iterator:()Ljava/util/Iterator;
#28 = NameAndType #46:#47 // hasNext:()Z
#29 = NameAndType #48:#49 // next:()Ljava/lang/Object;
#30 = Utf8 java/lang/Integer
#31 = NameAndType #50:#51 // intValue:()I
#32 = Class #52 // java/lang/System
#33 = NameAndType #53:#54 // out:Ljava/io/PrintStream;
#34 = Class #55 // java/io/PrintStream
#35 = NameAndType #56:#57 // println:(I)V
#36 = Utf8 ForEachLoop
#37 = Utf8 java/lang/Object
#38 = Utf8 java/util/List
#39 = Utf8 java/util/Iterator
#40 = Utf8 valueOf
#41 = Utf8 (I)Ljava/lang/Integer;
#42 = Utf8 of
#43 = Utf8 (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/List;
#44 = Utf8 iterator
#45 = Utf8 ()Ljava/util/Iterator;
#46 = Utf8 hasNext
#47 = Utf8 ()Z
#48 = Utf8 next
#49 = Utf8 ()Ljava/lang/Object;
#50 = Utf8 intValue
#51 = Utf8 ()I
#52 = Utf8 java/lang/System
#53 = Utf8 out
#54 = Utf8 Ljava/io/PrintStream;
#55 = Utf8 java/io/PrintStream
#56 = Utf8 println
#57 = Utf8 (I)V
{
public ForEachLoop();
descriptor: ()V
flags: (0x0001) 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
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=5, locals=4, args_size=1
0: iconst_1
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
.......
}
The above analysis shows that foreach loop has been replaced by java.util.Iterator . The
equivalent code would be:
List<Integer> list = List.of(1, 3, 6, 8, 9);
Iterator<Integer> itr = list.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
Syntactic sugar is a mean which allows Java to provide new syntax without
implementing that on JVM level. The syntactic syntax is converted
into another more general or low level construct by the compiler which can be understood by JVM. That way syntactic
constructs enable Java compilers to
implement new Java language features without changes to the JVM.
|