##### Overview

- Download PMD 3.7
- What's new in PMD 3.7
- PMD in the news
- PMD-related products and books
- Best practices
- Future directions
- Similar projects
- Credits
- License
- What does 'PMD' mean?

##### Usage

- Installation
- Command line usage
- Ant task usage
- Maven plugin usage
- IDE plugin usage
- Suppressing warnings
- Finding duplicated code
- JSP support

##### Customizing PMD

- Compiling PMD
- How to write a rule
- Writing XPath rules
- How to make a rule set
- How it works

##### For example

- Run PMD on a Sourceforge project

##### Rule Sets

- Index
- Basic
- Braces
- Code Size
- Clone
- Controversial
- Coupling
- Design
- Finalizers
- Import Statements
- J2EE
- Javabeans
- JUnit Tests
- Logging (Java)
- Logging (Jakarta)
- Migrating
- Naming
- Optimizations
- Strict Exceptions
- Strings
- Sun Security
- Unused Code
- Java Server Pages
- Java Server Faces

##### Project Documentation

- About PMD
- Project Info
- Project Reports
- Development Process

## 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.

This rule is defined by the following Java class: net.sourceforge.pmd.rules.optimization.LocalVariableCouldBeFinal

Here's an example of code that would trigger this rule:

    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 rule is defined by the following Java class: net.sourceforge.pmd.rules.optimization.MethodArgumentCouldBeFinal

Here's an example of code that would trigger this rule:

    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

This rule is defined by the following Java class: net.sourceforge.pmd.rules.optimization.AvoidInstantiatingObjectsInLoops

Here's an example of code that would trigger this rule:

    public class Something {
      public static void main( String as[] ) {
        for (int i = 0; i &lt; 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.

This rule is defined by the following XPath expression:

    //AllocationExpression
     /ClassOrInterfaceType[@Image='Vector' or @Image='java.util.Vector']

Here's an example of code that would trigger this rule:

    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.

This rule is defined by the following XPath expression:

    //PrimaryExpression
     [PrimaryPrefix/Name
      [ends-with(@Image, '.startsWith')]]
     [PrimarySuffix/Arguments/ArgumentList
      /Expression/PrimaryExpression/PrimaryPrefix
      /Literal
       [string-length(@Image)=3]
       [starts-with(@Image, '"')]
       [ends-with(@Image, '"')]
     ]

Here's an example of code that would trigger this rule:

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

### UseStringBufferForStringAppends

Finds usages of += for appending strings.

This rule is defined by the following XPath expression:

    //StatementExpression
        [PrimaryExpression/PrimaryPrefix/Name
            [@Image = ancestor::MethodDeclaration//LocalVariableDeclaration
                [./Type//ClassOrInterfaceType[@Image =
    'String']]/VariableDeclarator/VariableDeclaratorId/@Image]]
        //AssignmentOperator[@Compound='true']

Here's an example of code that would trigger this rule:

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

### UseArraysAsList

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

This rule is defined by the following XPath expression:

       //Statement[
        (ForStatement) and (count(.//IfStatement)=0)
       ]
       //StatementExpression[
        PrimaryExpression/PrimaryPrefix/Name[
         @Image = concat(ancestor::MethodDeclaration//LocalVariableDeclaration[
          ./Type//ClassOrInterfaceType[
           @Image = 'List' or @Image ='ArrayList'
          ]
         ]
         /VariableDeclarator/VariableDeclaratorId[
          count(..//AllocationExpression/ClassOrInterfaceType[
           @Image="ArrayList"
          ]
          )=1
         ]/@Image,".add")
        ]
       and
       PrimaryExpression/PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name
       [@Image = ancestor::MethodDeclaration//LocalVariableDeclaration
       [@Array="true"]/VariableDeclarator/VariableDeclaratorId/@Image]
       /../..[count(.//PrimarySuffix)
       =1]/PrimarySuffix/Expression/PrimaryExpression/PrimaryPrefix
       /Name
       ]

Here's an example of code that would trigger this rule:

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

### AvoidArrayLoops

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

This rule is defined by the following XPath expression:

    //Statement[(ForStatement or WhileStatement) and
    count(*//AssignmentOperator)=1
    and
    */Statement
    [
    ./Block/BlockStatement/Statement/StatementExpression/PrimaryExpression
    /PrimaryPrefix/Name/../../PrimarySuffix/Expression
    [(PrimaryExpression or AdditiveExpression) and count
    (.//PrimaryPrefix/Name)=1]//PrimaryPrefix/Name/@Image
    and
    ./Block/BlockStatement/Statement/StatementExpression/Expression/PrimaryExpression
    /PrimaryPrefix/Name/../../PrimarySuffix[count
    (..//PrimarySuffix)=1]/Expression[(PrimaryExpression
    or AdditiveExpression) and count(.//PrimaryPrefix/Name)=1]
    //PrimaryPrefix/Name/@Image
    ]]

Here's an example of code that would trigger this rule:

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

            }
        }