Wednesday, September 28, 2011

PMD - Optimization Rules

This is the fifteenth installment of explanation of PMD rules covering Optimization Rules. These rules will ensure that we get optimum performance from the applications.

Optimization Rules

These rules deal with different optimizations that generally apply to performance best practices.

LocalVariableCouldBeFinal

A local variable assigned only once can be declared final.

Example

public class Bar {
public void foo () {
  String a = "a"; //if a will not be assigned again it is better to do this:
  final String b = "b";
}
}

MethodArgumentCouldBeFinal

A method argument that is never assigned can be declared final. This will ensure that the value is not changed inadvertently in future.

Example

public void foo (String param) {
  // do stuff with param never assigning it
  // better: public void foo (final String param) {
}

AvoidInstantiatingObjectsInLoops

Detects when a new object is created inside a loop. There will be situations where this will be unavoidable and so this rule can be violated when required.

Example

public class Something {
  public static void main( String as[] ) {  
    for (int i = 0; i < 10; i++) {
      Foo f = new Foo(); //Avoid this whenever you can it's really expensive
    }
  }
}

UseArrayListInsteadOfVector

ArrayList is a much better Collection implementation than Vector.

Example

public class SimpleTest extends TestCase {
public void testX() {
  Collection c = new Vector();
  // This achieves the same with much better performance
  // Collection c = new ArrayList();
}
}

SimplifyStartsWith

Since it passes in a literal of length 1, this call to String.startsWith can be rewritten using String.charAt(0) to save some time.

Example

public class Foo {
  boolean checkIt(String x) {
      return x.startsWith("a");
  }
}

UseStringBufferForStringAppends

Finds usages of += for appending strings. This greatly improves the performance. Better still it is sure that the variable will be accessed by only one thread then it is better to use StringBuilder as the methods of this class are not synchronized. The StringBuffer should be used only if we expect to be appending to the buffer from multiple threads.

Example

public class Foo {
void bar() {
  String a;
  a = "foo";
  a += " bar";
  // better would be:
  // StringBuffer a = new StringBuffer("foo");
  // a.append(" bar);
}
}

UseArraysAsList

The java.util.Arrays class has a "asList" method that should be used when you want to create a new List from an array of objects. It is faster than executing a loop to copy all the elements of the array one by one

Example

public class Test {
    public void foo(Integer[] ints) {
    // could just use Arrays.asList(ints)
     List l= new ArrayList(10);
     for (int i=0; i< 100; i++) {
      l.add(ints[i]);
     }
     for (int i=0; i< 100; i++) {
      l.add(a[i].toString()); // won't trigger the rule
     }
    }
   }

AvoidArrayLoops

Instead of copying data between two arrays, use System.arraycopy method

Example

public class Test {
public void bar() {
  int[] a = new int[10];
  int[] b = new int[10];
  for (int i=0;i <10;i++) {
   b[i]=a[i];
  }
}
}
            // this will trigger the rule
            for (int i=0;i<10;i++) {
             b[i]=a[c[i]];
            }
 
        }
    }

UnnecessaryWrapperObjectCreation

Parsing method should be called directly instead.

Example

public int convert(String s) {
  int i, i2;
 
  i = Integer.valueOf(s).intValue(); // this wastes an object
  i = Integer.parseInt(s); // this is better
 
  i2 = Integer.valueOf(i).intValue(); // this wastes an object
  i2 = i; // this is better
 
  String s3 = Integer.valueOf(i2).toString(); // this wastes an object
  s3 = Integer.toString(i2); // this is better
 
  return i2;
}

AddEmptyString

Finds empty string literals which are being added. This is an inefficient way to convert any type to a String.

Example

String s = "" + 123; // bad 
        String t = Integer.toString(456); // ok

No comments: