git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@7377 51baf565-9d33-0410-a72c-fc3788e3496d
438 lines
13 KiB
XML
438 lines
13 KiB
XML
<?xml version="1.0"?>
|
|
|
|
<ruleset name="Optimization"
|
|
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd"
|
|
xsi:noNamespaceSchemaLocation="http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
|
|
<description>
|
|
These rules deal with different optimizations that generally apply to best practices.
|
|
</description>
|
|
|
|
<rule name="LocalVariableCouldBeFinal"
|
|
since="2.2"
|
|
message="Local variable ''{0}'' could be declared final"
|
|
class="net.sourceforge.pmd.lang.java.rule.optimizations.LocalVariableCouldBeFinalRule"
|
|
externalInfoUrl="http://pmd.sourceforge.net/rules/java/optimizations.html#LocalVariableCouldBeFinal">
|
|
<description>
|
|
A local variable assigned only can be declared final once.
|
|
</description>
|
|
<priority>3</priority>
|
|
<example>
|
|
<![CDATA[
|
|
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";
|
|
}
|
|
}
|
|
]]>
|
|
</example>
|
|
</rule>
|
|
|
|
<rule name="MethodArgumentCouldBeFinal"
|
|
since="2.2"
|
|
message="Parameter ''{0}'' is not assigned and could be declared final"
|
|
class="net.sourceforge.pmd.lang.java.rule.optimizations.MethodArgumentCouldBeFinalRule"
|
|
externalInfoUrl="http://pmd.sourceforge.net/rules/java/optimizations.html#MethodArgumentCouldBeFinal">
|
|
<description>
|
|
A method argument that is never re-assigned within the method can be declared final.
|
|
</description>
|
|
<priority>3</priority>
|
|
<example>
|
|
<![CDATA[
|
|
public void foo1 (String param) { // do stuff with param never assigning it
|
|
|
|
}
|
|
|
|
public void foo2 (final String param) { // better, do stuff with param never assigning it
|
|
|
|
}
|
|
]]>
|
|
</example>
|
|
</rule>
|
|
|
|
<rule name="AvoidInstantiatingObjectsInLoops"
|
|
since="2.2"
|
|
message="Avoid instantiating new objects inside loops"
|
|
class="net.sourceforge.pmd.lang.java.rule.optimizations.AvoidInstantiatingObjectsInLoopsRule"
|
|
externalInfoUrl="http://pmd.sourceforge.net/rules/java/optimizations.html#AvoidInstantiatingObjectsInLoops">
|
|
<description>
|
|
New objects created within loops should be checked to see if they can created outside and reused.
|
|
</description>
|
|
<priority>3</priority>
|
|
<example>
|
|
<![CDATA[
|
|
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
|
|
}
|
|
}
|
|
}
|
|
]]>
|
|
</example>
|
|
</rule>
|
|
|
|
<rule name="UseArrayListInsteadOfVector"
|
|
language="java"
|
|
since="3.0"
|
|
message="Use ArrayList instead of Vector"
|
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
externalInfoUrl="http://pmd.sourceforge.net/rules/java/optimizations.html#UseArrayListInsteadOfVector">
|
|
<description>
|
|
ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required.
|
|
</description>
|
|
<priority>3</priority>
|
|
<properties>
|
|
<property name="xpath">
|
|
<value>
|
|
<![CDATA[
|
|
//AllocationExpression
|
|
/ClassOrInterfaceType[@Image='Vector' or @Image='java.util.Vector']
|
|
]]>
|
|
</value>
|
|
</property>
|
|
</properties>
|
|
<example>
|
|
<![CDATA[
|
|
public class SimpleTest extends TestCase {
|
|
public void testX() {
|
|
Collection c1 = new Vector();
|
|
Collection c2 = new ArrayList(); // achieves the same with much better performance
|
|
}
|
|
}
|
|
]]>
|
|
</example>
|
|
</rule>
|
|
|
|
<rule name="SimplifyStartsWith"
|
|
language="java"
|
|
since="3.1"
|
|
message="This call to String.startsWith can be rewritten using String.charAt(0)"
|
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
externalInfoUrl="http://pmd.sourceforge.net/rules/java/optimizations.html#SimplifyStartsWith">
|
|
<description>
|
|
Since it passes in a literal of length 1, calls to (string).startsWith can be rewritten using (string).charAt(0)
|
|
at the expense of some readability.
|
|
</description>
|
|
<priority>3</priority>
|
|
<properties>
|
|
<property name="xpath">
|
|
<value>
|
|
<![CDATA[
|
|
//PrimaryExpression
|
|
[PrimaryPrefix/Name
|
|
[ends-with(@Image, '.startsWith')]]
|
|
[PrimarySuffix/Arguments/ArgumentList
|
|
/Expression/PrimaryExpression/PrimaryPrefix
|
|
/Literal
|
|
[string-length(@Image)=3]
|
|
[starts-with(@Image, '"')]
|
|
[ends-with(@Image, '"')]
|
|
]
|
|
]]>
|
|
</value>
|
|
</property>
|
|
</properties>
|
|
<example>
|
|
<![CDATA[
|
|
public class Foo {
|
|
|
|
boolean checkIt(String x) {
|
|
return x.startsWith("a"); // suboptimal
|
|
}
|
|
|
|
boolean fasterCheckIt(String x) {
|
|
return x.charAt(0) == 'a'; // faster approach
|
|
}
|
|
}
|
|
]]>
|
|
</example>
|
|
</rule>
|
|
|
|
<rule name="UseStringBufferForStringAppends"
|
|
since="3.1"
|
|
message="Prefer StringBuffer over += for concatenating strings"
|
|
class="net.sourceforge.pmd.lang.java.rule.optimizations.UseStringBufferForStringAppendsRule"
|
|
externalInfoUrl="http://pmd.sourceforge.net/rules/java/optimizations.html#UseStringBufferForStringAppends">
|
|
<description>
|
|
The use of the '+=' operator for appending strings causes the JVM to create and use an internal StringBuffer.
|
|
If a non-trivial number of these concatenations are being used then the explicit use of a StringBuffer or
|
|
StringBuilder is recommended to avoid this.
|
|
</description>
|
|
<priority>3</priority>
|
|
<example>
|
|
<![CDATA[
|
|
public class Foo {
|
|
void bar() {
|
|
String a;
|
|
a = "foo";
|
|
a += " bar";
|
|
// better would be:
|
|
// StringBuffer a = new StringBuffer("foo");
|
|
// a.append(" bar);
|
|
}
|
|
}
|
|
]]>
|
|
</example>
|
|
</rule>
|
|
|
|
<rule name="UseArraysAsList"
|
|
language="java"
|
|
since="3.5"
|
|
message="Use asList instead of tight loops"
|
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
externalInfoUrl="http://pmd.sourceforge.net/rules/java/optimizations.html#UseArraysAsList">
|
|
<description>
|
|
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.
|
|
</description>
|
|
<priority>3</priority>
|
|
<properties>
|
|
<property name="xpath">
|
|
<value>
|
|
<![CDATA[
|
|
//Statement[
|
|
(ForStatement) and (count(.//IfStatement)=0)
|
|
]
|
|
//StatementExpression[
|
|
PrimaryExpression/PrimaryPrefix/Name[
|
|
substring-before(@Image,'.add') = ancestor::MethodDeclaration//LocalVariableDeclaration[
|
|
./Type//ClassOrInterfaceType[
|
|
@Image = 'Collection' or
|
|
@Image = 'List' or @Image='ArrayList'
|
|
]
|
|
]
|
|
/VariableDeclarator/VariableDeclaratorId[
|
|
count(..//AllocationExpression/ClassOrInterfaceType[
|
|
@Image="ArrayList"
|
|
]
|
|
)=1
|
|
]/@Image
|
|
]
|
|
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
|
|
]
|
|
]]>
|
|
</value>
|
|
</property>
|
|
</properties>
|
|
<example>
|
|
<![CDATA[
|
|
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
|
|
}
|
|
}
|
|
}
|
|
]]>
|
|
</example>
|
|
</rule>
|
|
|
|
|
|
<rule name="AvoidArrayLoops"
|
|
language="java"
|
|
since="3.5"
|
|
message="System.arraycopy is more efficient"
|
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
externalInfoUrl="http://pmd.sourceforge.net/rules/java/optimizations.html#AvoidArrayLoops">
|
|
<description>
|
|
Instead of copying data between two arrays, use System.arraycopy method.
|
|
</description>
|
|
<priority>3</priority>
|
|
<properties>
|
|
<property name="xpath">
|
|
<value>
|
|
<![CDATA[
|
|
//Statement[(ForStatement or WhileStatement) and
|
|
count(*//AssignmentOperator[@Image = '='])=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
|
|
]]
|
|
]]>
|
|
</value>
|
|
</property>
|
|
</properties>
|
|
<example>
|
|
<![CDATA[
|
|
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]];
|
|
}
|
|
|
|
}
|
|
}
|
|
]]>
|
|
</example>
|
|
</rule>
|
|
|
|
<rule name="UnnecessaryWrapperObjectCreation"
|
|
since="3.8"
|
|
message="Unnecessary wrapper object creation"
|
|
class="net.sourceforge.pmd.lang.java.rule.optimizations.UnnecessaryWrapperObjectCreationRule"
|
|
externalInfoUrl="http://pmd.sourceforge.net/rules/java/optimizations.html#UnnecessaryWrapperObjectCreation">
|
|
<description>
|
|
Most wrapper classes provide static conversion methods that avoid the need to create intermediate objects
|
|
just to create the primitive forms. Using these avoids the cost of creating objects that also need to be
|
|
garbage-collected later.
|
|
</description>
|
|
<priority>3</priority>
|
|
<example>
|
|
<![CDATA[
|
|
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;
|
|
}
|
|
]]>
|
|
</example>
|
|
</rule>
|
|
|
|
<rule name="AddEmptyString"
|
|
language="java"
|
|
since="4.0"
|
|
message="Do not add empty strings"
|
|
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
externalInfoUrl="http://pmd.sourceforge.net/rules/java/optimizations.html#AddEmptyString">
|
|
<description>
|
|
The conversion of literals to strings by concatenating them with empty strings is inefficient.
|
|
It is much better to use one of the type-specific toString() methods instead.
|
|
</description>
|
|
<priority>3</priority>
|
|
<properties>
|
|
<property name="xpath">
|
|
<value>
|
|
<![CDATA[
|
|
//AdditiveExpression/PrimaryExpression/PrimaryPrefix/Literal[@Image='""']
|
|
]]>
|
|
</value>
|
|
</property>
|
|
</properties>
|
|
<example>
|
|
<![CDATA[
|
|
String s = "" + 123; // inefficient
|
|
String t = Integer.toString(456); // preferred approach
|
|
]]>
|
|
</example>
|
|
</rule>
|
|
|
|
<rule name="RedundantFieldInitializer"
|
|
language="java"
|
|
since="5.0"
|
|
message="Avoid using redundant field initializer for ''${variableName}''"
|
|
class="net.sourceforge.pmd.lang.java.rule.optimizations.RedundantFieldInitializerRule"
|
|
externalInfoUrl="http://pmd.sourceforge.net/rules/java/optimizations.html#RedundantFieldInitializer">
|
|
<description>
|
|
Java will initialize fields with defaults so any explicit initialization of those same defaults
|
|
is redundant and results in a larger class file (approximately three additional bytecode
|
|
instructions per field).
|
|
</description>
|
|
<priority>3</priority>
|
|
<example>
|
|
<![CDATA[
|
|
public class C {
|
|
boolean b = false; // examples of redundant initializers
|
|
byte by = 0;
|
|
short s = 0;
|
|
char c = 0;
|
|
int i = 0;
|
|
long l = 0;
|
|
|
|
float f = .0f; // all possible float literals
|
|
doable d = 0d; // all possible double literals
|
|
Object o = null;
|
|
|
|
MyClass mca[] = null;
|
|
int i1 = 0, ia1[] = null;
|
|
|
|
class Nested {
|
|
boolean b = false;
|
|
}
|
|
}
|
|
]]>
|
|
</example>
|
|
</rule>
|
|
|
|
<rule name="PrematureDeclaration"
|
|
language="java"
|
|
since="5.0"
|
|
message="Avoid declaring a variable if it is unreferenced before a possible exit point."
|
|
class="net.sourceforge.pmd.lang.java.rule.optimizations.PrematureDeclarationRule"
|
|
externalInfoUrl="http://pmd.sourceforge.net/rules/java/optimizations.html#PrematureDeclaration">
|
|
<description>
|
|
Checks for variables that are defined before they might be used. A reference is deemed to be premature if it is created right before a block of code that doesn'tuse it that also has the ability to return or throw an exception.
|
|
</description>
|
|
<priority>3</priority>
|
|
<example>
|
|
<![CDATA[
|
|
public int getLength(String[] strings) {
|
|
|
|
int length = 0; // declared prematurely
|
|
|
|
if (strings == null || strings.length == 0) return 0;
|
|
|
|
for (String str : strings) {
|
|
length += str.length();
|
|
}
|
|
|
|
return length;
|
|
}
|
|
]]>
|
|
</example>
|
|
</rule>
|
|
|
|
<!--
|
|
other optimization should be like avoiding
|
|
"" + int
|
|
or "" + (int) i
|
|
and String.valueOf(int)
|
|
|
|
and using Integer.toString(int)
|
|
|
|
IntegerToStringShouldBeUsed
|
|
LongToStringShouldBeUsed
|
|
BooleanToStringShouldBeUsed
|
|
-->
|
|
|
|
</ruleset> |