Code Inspection

I recently got the chance to participate in another code inspection, in which among other things, the following line of code was heavily criticized for using String concatenation on constants and not using a StringBuffer object for the string operation in general.

FindFile.FindFileInClasspath( kPropFilePrefix + "*"+ kPropFileSuffix + kKeyProperties, vPropFiles );

This is from a J2EE project and the code is used in a background thread and executes every couple of seconds.

Since I also do some work in the field of embedded software development, which usually involves memory, processing speed, and power constraints, I can really appreciate code level optimizations. However, this is not a MIDlet project nor does the code run all that often. Moreover, the concatenation really does add some clarity to what the code is doing and what the parameter’s value is when the static method is called.

Now, to satisfy the optimization junkies, I have created the following small sample:

class Test {
  public static final String PREFIX="abc";
  public static final String SUFFIX="123";
  public Test(String t) {
    String s = Test.PREFIX + "*" + Test.SUFFIX + t;
    System.out.println( s );
  }
  public static void main(String[] args) {
    new Test(args[0]);
  }
}

Compiling followed by disassembling shows the following code:

C:\temp\test>javac Test.java
C:\temp\test>javap -c Test

Compiled from "Test.java"
class Test extends java.lang.Object{
public static final java.lang.String PREFIX;
public static final java.lang.String SUFFIX; 
public Test(java.lang.String);
Code:
0:   aload_0
1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
4:   new     #2; //class StringBuffer
7:   dup
8:   invokespecial   #3; //Method java/lang/StringBuffer."<init>":()V
11:  ldc     #4; //String abc*123
13:  invokevirtual   #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
16:  aload_1
17:  invokevirtual   #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
20:  invokevirtual   #6; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
23:  astore_2
24:  getstatic       #7; //Field java/lang/System.out:Ljava/io/PrintStream;
27:  aload_2
28:  invokevirtual   #8; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
31:  return
public static void main(java.lang.String[]);
Code:
0:   new     #9; //class Test
3:   dup
4:   aload_0
5:   iconst_0
6:   aaload
7:   invokespecial   #10; //Method "<init>":(Ljava/lang/String;)V
10:  pop
11:  return
}

If you look at the disassembled code you will find out that the compiler combines the String constants into one and also uses a StringBuffer for the concatenation that needs to be done at runtime.

 

Leave a Reply