Since: PMD 4.0
Priority: Medium (3)
The conversion of literals to strings by concatenating them with empty strings is inefficient.It is much better to use one of the type-specifictoString() methods instead orString.valueOf().
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.AddEmptyStringRule
Example(s):
Strings=""+123;// inefficientStringt=Integer.toString(456);// preferred approachUse this rule by referencing it:
<ruleref="category/java/performance.xml/AddEmptyString"/>Since: PMD 3.5
Priority: Medium (3)
Avoid concatenating characters as strings in StringBuffer/StringBuilder.append methods.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.AppendCharacterWithCharRule
Example(s):
StringBuffersb=newStringBuffer();sb.append("a");// avoid thisStringBuffersb=newStringBuffer();sb.append('a');// use this insteadUse this rule by referencing it:
<ruleref="category/java/performance.xml/AppendCharacterWithChar"/>Since: PMD 3.5
Priority: Medium (3)
Instead of manually copying data between two arrays, use the more efficientArrays.copyOforSystem.arraycopy method instead.
To copy only part of the array, useArrays.copyOfRange orSystem.arraycopy.
If you want to copy/move elements inside thesame array (e.g. shift the elements), useSystem.arraycopy.
This rule is defined by the following XPath expression:
//(ForStatement[ForUpdate//(UnaryExpression[@Operator=('++','--')]|AssignmentExpression[@Operator=('+=','-=')][NumericLiteral[@Image='1']])]|WhileStatement|DoStatement)[not(.//ContinueStatement)][not(.//BreakStatement)][not(.//ThrowStatement)][not(.//ReturnStatement)][count(Block//AssignmentExpression[@Operator='='](: no nested arrays or method calls as array index :)[count(ArrayAccess[not(.//ArrayAccess)][not(.//MethodCall)])=2](: array access indexes must be same (excluding constants) :)[deep-equal(sort(distinct-values(ArrayAccess[1]/(VariableAccess[2]|InfixExpression//VariableAccess)(: don't consider array length accesses :)[not(parent::FieldAccess[@Name='length'])][(: exclude referenced constants :)not(@Name=(ancestor::MethodDeclaration|//FieldDeclaration)//VariableDeclarator[NumericLiteral][not(../../../parent::ForInit)]/VariableId/@Name)or(: include loop variable :)@Name=ancestor::ForStatement/ForInit/LocalVariableDeclaration/VariableDeclarator/VariableId/@Name]/@Name)),sort(distinct-values(ArrayAccess[2]/(VariableAccess[2]|InfixExpression//VariableAccess)(: don't consider array length accesses :)[not(parent::FieldAccess[@Name='length'])][(: exclude referenced constants :)not(@Name=(ancestor::MethodDeclaration|//FieldDeclaration)//VariableDeclarator[NumericLiteral][not(../../../parent::ForInit)]/VariableId/@Name)or(: include loop variable :)@Name=ancestor::ForStatement/ForInit/LocalVariableDeclaration/VariableDeclarator/VariableId/@Name]/@Name)))])=1]Example(s):
classScratch{voidcopy_a_to_b(){int[]a=newint[10];int[]b=newint[10];for(inti=0;i<a.length;i++){b[i]=a[i];}// equivalentb=Arrays.copyOf(a,a.length);// equivalentSystem.arraycopy(a,0,b,0,a.length);int[]c=newint[10];// this will not trigger the rulefor(inti=0;i<c.length;i++){b[i]=a[c[i]];}}}classScratch{voidshift_left(int[]a){for(inti=0;i<a.length-1;i++){a[i]=a[i+1];}// equivalentSystem.arraycopy(a,1,a,0,a.length-1);}voidshift_right(int[]a){for(inti=a.length-1;i>0;i--){a[i]=a[i-1];}// equivalentSystem.arraycopy(a,0,a,1,a.length-1);}}Use this rule by referencing it:
<ruleref="category/java/performance.xml/AvoidArrayLoops"/>Since: PMD 6.25.0
Priority: Medium (3)
Problem:java.util.Calendar is a heavyweight object and expensive to create. It should only be used, ifcalendar calculations are needed.
Solution: Usenew Date(), Java 8+java.time.LocalDateTime.now() orZonedDateTime.now().
This rule is defined by the following XPath expression:
//MethodCall[pmd-java:matchesSig("java.util.Calendar#getTime()")orpmd-java:matchesSig("java.util.Calendar#getTimeInMillis()")][*[1][local-name()=('MethodCall','ConstructorCall')][pmd-java:matchesSig("java.util.Calendar#getInstance()")orpmd-java:matchesSig("java.util.GregorianCalendar#getInstance()")orpmd-java:matchesSig("java.util.GregorianCalendar#new()")]]|//MethodCall[pmd-java:matchesSig("java.util.Calendar#getTime()")orpmd-java:matchesSig("java.util.Calendar#getTimeInMillis()")][*[1][local-name()='VariableAccess']](: ignore if .set* or .add or .clear or .roll is called on the variable :)[not(VariableAccess/@Name=ancestor::Block//MethodCall[starts-with(@MethodName,"set")or@MethodName=("add","clear","roll")]/VariableAccess/@Name)](: variable must be initialized with getInstance :)[VariableAccess/@Name=ancestor::Block//LocalVariableDeclaration/VariableDeclarator[(MethodCall|ConstructorCall)[pmd-java:matchesSig("java.util.Calendar#getInstance()")orpmd-java:matchesSig("java.util.GregorianCalendar#getInstance()")orpmd-java:matchesSig("java.util.GregorianCalendar#new()")]]/VariableId/@Name]|//ConstructorCall[pmd-java:typeIs("org.joda.time.DateTime")orpmd-java:typeIs("org.joda.time.LocalDateTime")][ArgumentList[(MethodCall|ConstructorCall)[pmd-java:matchesSig("java.util.Calendar#getInstance()")orpmd-java:matchesSig("java.util.GregorianCalendar#getInstance()")orpmd-java:matchesSig("java.util.GregorianCalendar#new()")]]]Example(s):
importjava.time.LocalDateTime;importjava.util.Calendar;importjava.util.Date;publicclassDateStuff{privateDatebad1(){returnCalendar.getInstance().getTime();// now}privateDategood1a(){returnnewDate();// now}privateLocalDateTimegood1b(){returnLocalDateTime.now();}privatelongbad2(){returnCalendar.getInstance().getTimeInMillis();}privatelonggood2(){returnSystem.currentTimeMillis();}}Use this rule by referencing it:
<ruleref="category/java/performance.xml/AvoidCalendarDateCreation"/>Since: PMD 6.0.0
Priority: High (1)
Minimum Language Version: Java 1.7
The FileInputStream and FileOutputStream classes contains a finalizer method which will cause garbagecollection pauses.SeeJDK-8080225 for details.
The FileReader and FileWriter constructors instantiate FileInputStream and FileOutputStream,again causing garbage collection issues while finalizer methods are called.
Files.newInputStream(Paths.get(fileName)) instead ofnew FileInputStream(fileName).Files.newOutputStream(Paths.get(fileName)) instead ofnew FileOutputStream(fileName).Files.newBufferedReader(Paths.get(fileName)) instead ofnew FileReader(fileName).Files.newBufferedWriter(Paths.get(fileName)) instead ofnew FileWriter(fileName).Please note, that thejava.nio API does not throw aFileNotFoundException anymore, insteadit throws aNoSuchFileException. If your code dealt explicitly with aFileNotFoundException,then this needs to be adjusted. Both exceptions are subclasses ofIOException, so catchingthat one covers both.
This rule is defined by the following XPath expression:
//ConstructorCall/ClassType[pmd-java:typeIs('java.io.FileInputStream')orpmd-java:typeIs('java.io.FileOutputStream')orpmd-java:typeIs('java.io.FileReader')orpmd-java:typeIs('java.io.FileWriter')]Example(s):
// these instantiations cause garbage collection pauses, even if properly closedFileInputStreamfis=newFileInputStream(fileName);FileOutputStreamfos=newFileOutputStream(fileName);FileReaderfr=newFileReader(fileName);FileWriterfw=newFileWriter(fileName);// the following instantiations help prevent Garbage Collection pauses, no finalizationtry(InputStreamis=Files.newInputStream(Paths.get(fileName))){}try(OutputStreamos=Files.newOutputStream(Paths.get(fileName))){}try(BufferedReaderbr=Files.newBufferedReader(Paths.get(fileName),StandardCharsets.UTF_8)){}try(BufferedWriterwr=Files.newBufferedWriter(Paths.get(fileName),StandardCharsets.UTF_8)){}Use this rule by referencing it:
<ruleref="category/java/performance.xml/AvoidFileStream"/>Since: PMD 2.2
Priority: Medium (3)
New objects created within loops should be checked to see if they can created outside them and reused.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.AvoidInstantiatingObjectsInLoopsRule
Example(s):
publicclassSomething{publicstaticvoidmain(Stringas[]){for(inti=0;i<10;i++){Foof=newFoo();// Avoid this whenever you can it's really expensive}}}Use this rule by referencing it:
<ruleref="category/java/performance.xml/AvoidInstantiatingObjectsInLoops"/>Since: PMD 3.9
Priority: Medium (3)
Don’t create instances of already existing BigInteger (BigInteger.ZERO,BigInteger.ONE),for Java 1.5 onwards, BigInteger.TEN and BigDecimal (BigDecimal.ZERO,BigDecimal.ONE,BigDecimal.TEN) andfor Java 9 onwardsBigInteger.TWO.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.BigIntegerInstantiationRule
Example(s):
BigIntegerbi1=newBigInteger("1");// reference BigInteger.ONE insteadBigIntegerbi2=newBigInteger("0");// reference BigInteger.ZERO insteadBigIntegerbi3;bi3=newBigInteger("0");// reference BigInteger.ZERO insteadBigDecimalbd1=newBigDecimal(0);// reference BigDecimal.ZERO insteadBigDecimalbd2=newBigDecimal("0.");// reference BigDecimal.ZERO insteadBigDecimalbd3=newBigDecimal(10);// reference BigDecimal.TEN insteadUse this rule by referencing it:
<ruleref="category/java/performance.xml/BigIntegerInstantiation"/>Since: PMD 5.1
Priority: Medium (3)
Consecutive calls to StringBuffer/StringBuilder .append should be chained, reusing the target object. This can improve the performanceby producing a smaller bytecode, reducing overhead and improving inlining. A complete analysis can be foundhere
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.ConsecutiveAppendsShouldReuseRule
Example(s):
Stringfoo=" ";StringBufferbuf=newStringBuffer();buf.append("Hello");// poorbuf.append(foo);buf.append("World");StringBufferbuf=newStringBuffer();buf.append("Hello").append(foo).append("World");// goodUse this rule by referencing it:
<ruleref="category/java/performance.xml/ConsecutiveAppendsShouldReuse"/>Since: PMD 3.5
Priority: Medium (3)
Consecutively calling StringBuffer/StringBuilder.append(…) with literals should be avoided.Since the literals are constants, they can already be combined into a single String literal and this Stringcan be appended in a single method call.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.ConsecutiveLiteralAppendsRule
Example(s):
StringBuilderbuf=newStringBuilder();buf.append("Hello").append(" ").append("World");// poorbuf.append("Hello World");// goodbuf.append('h').append('e').append('l').append('l').append('o');// poorbuf.append("hello");// goodbuf.append(1).append('m');// poorbuf.append("1m");// goodThis rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| threshold | 1 | Max consecutive appends |
Use this rule with the default properties by just referencing it:
<ruleref="category/java/performance.xml/ConsecutiveLiteralAppends"/>Use this rule and customize it:
<ruleref="category/java/performance.xml/ConsecutiveLiteralAppends"><properties><propertyname="threshold"value="1"/></properties></rule>Since: PMD 3.6
Priority: Medium (3)
String.trim().length() == 0 (or String.trim().isEmpty() for the same reason) is an inefficientway to check if a String is really blank, as it creates a new String object just to check its size.Consider creating a static function that loops through a string, checking Character.isWhitespace()on each character and returning false if a non-whitespace character is found. A Smarter code tocheck for an empty string would be:
privatebooleancheckTrimEmpty(Stringstr){for(inti=0;i<str.length();i++){if(!Character.isWhitespace(str.charAt(i))){returnfalse;}}returntrue;}You can refer to Apache’s StringUtils#isBlank (in commons-lang),Spring’s StringUtils#hasText (in the Spring framework) or Google’sCharMatcher#whitespace (in Guava) for existing implementations (some mightinclude the check for != null).
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.InefficientEmptyStringCheckRule
Example(s):
publicvoidbar(Stringstring){if(string!=null&&string.trim().length()>0){doSomething();}}Use this rule by referencing it:
<ruleref="category/java/performance.xml/InefficientEmptyStringCheck"/>Since: PMD 3.4
Priority: Medium (3)
Avoid concatenating non-literals in a StringBuffer constructor or append() since intermediate buffers willneed to be be created and destroyed by the JVM.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.InefficientStringBufferingRule
Example(s):
// Avoid this, two buffers are actually being created hereStringBuffersb=newStringBuffer("tmp = "+System.getProperty("java.io.tmpdir"));// do this insteadStringBuffersb=newStringBuffer("tmp = ");sb.append(System.getProperty("java.io.tmpdir"));Use this rule by referencing it:
<ruleref="category/java/performance.xml/InefficientStringBuffering"/>Since: PMD 3.6
Priority: Medium (3)
Failing to pre-size a StringBuffer or StringBuilder properly could cause it to re-size many timesduring runtime. This rule attempts to determine the total number the characters that are actuallypassed into StringBuffer.append(), but represents a best guess "worst case" scenario. An emptyStringBuffer/StringBuilder constructor initializes the object to 16 characters. This defaultis assumed if the length of the constructor can not be determined.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.InsufficientStringBufferDeclarationRule
Example(s):
StringBuilderbad=newStringBuilder();bad.append("This is a long string that will exceed the default 16 characters");StringBuildergood=newStringBuilder(41);good.append("This is a long string, which is pre-sized");Use this rule by referencing it:
<ruleref="category/java/performance.xml/InsufficientStringBufferDeclaration"/>Since: PMD 1.8
Priority: Medium (3)
Minimum Language Version: Java 1.6
Calls to a collection’stoArray(E[]) method should specify a target array of zero size. This allows the JVMto optimize the memory allocation and copying as much as possible.
Previous versions of this rule (pre PMD 6.0.0) suggested the opposite, but current JVM implementationsperform always better, when they have full control over the target array. And allocation an array viareflection is nowadays as fast as the direct allocation.
See alsoArrays of Wisdom of the Ancients
Note: If you don’t need an array of the correct type, then the simpletoArray() method without an arrayis faster, but returns only an array of typeObject[].
This rule is defined by the following XPath expression:
//MethodCall[pmd-java:matchesSig("java.util.Collection#toArray(_)")][ArgumentList/ArrayAllocation/ArrayType/ArrayDimensions/ArrayDimExpr[not(NumericLiteral[@Image="0"])]]Example(s):
List<Foo>foos=getFoos();// much better; this one allows the jvm to allocate an array of the correct size and effectively skip// the zeroing, since each array element will be overridden anywaysFoo[]fooArray=foos.toArray(newFoo[0]);// inefficient, the array needs to be zeroed out by the jvm before it is handed over to the toArray methodFoo[]fooArray=foos.toArray(newFoo[foos.size()]);Use this rule by referencing it:
<ruleref="category/java/performance.xml/OptimizableToArrayCall"/>Since: PMD 5.0
Priority: Medium (3)
Java will initialize fields with known default values so any explicit initialization of those same defaultsis redundant and results in a larger class file (approximately three additional bytecode instructions per field).
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.RedundantFieldInitializerRule
Example(s):
publicclassC{booleanb=false;// examples of redundant initializersbyteby=0;shorts=0;charc=0;inti=0;longl=0;floatf=.0f;// all possible float literalsdoubled=0d;// all possible double literalsObjecto=null;MyClassmca[]=null;inti1=0,ia1[]=null;classNested{booleanb=false;}}Use this rule by referencing it:
<ruleref="category/java/performance.xml/RedundantFieldInitializer"/>Since: PMD 1.0
Priority: Medium High (2)
Avoid instantiating String objects; this is usually unnecessary since they are immutable and can be safely shared.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.StringInstantiationRule
Example(s):
privateStringbar=newString("bar");// just do a String bar = "bar";Use this rule by referencing it:
<ruleref="category/java/performance.xml/StringInstantiation"/>Since: PMD 1.0
Priority: Medium (3)
Avoid calling toString() on objects already known to be string instances; this is unnecessary.
This rule is defined by the following XPath expression:
//MethodCall[pmd-java:matchesSig("java.lang.String#toString()")]Example(s):
privateStringbaz(){Stringbar="howdy";returnbar.toString();}Use this rule by referencing it:
<ruleref="category/java/performance.xml/StringToString"/>Deprecated
This rule has been renamed. Use instead:TooFewBranchesForSwitch
Deprecated
Since: PMD 4.2
Priority: Medium (3)
Switch statements are intended to be used to support complex branching behaviour. Using a switch for only a fewcases is ill-advised, since switches are not as easy to understand as if-else statements. In these cases use theif-else statement to increase code readability.
Note: This rule was named TooFewBranchesForASwitchStatement before PMD 7.7.0.
This rule is defined by the following XPath expression:
//(SwitchStatement|SwitchExpression)[count(*)>1](: ignore empty switch blocks :)[(count(*/SwitchLabel/*)+count(*/SwitchLabel[@Default=true()]))<$minimumNumberCaseForASwitch](: do not consider exhaustive switches unless there is a default case :)[@Exhaustive=false()or@DefaultCase=true()]Example(s):
// With a minimumNumberCaseForASwitch of 3publicclassFoo{publicvoidbar(intcondition){switch(condition){case1:instruction;break;default:break;// not enough for a 'switch' stmt, a simple 'if' stmt would have been more appropriate}}}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| minimumNumberCaseForASwitch | 3 | Minimum number of branches for a switch |
Use this rule with the default properties by just referencing it:
<ruleref="category/java/performance.xml/TooFewBranchesForASwitchStatement"/>Use this rule and customize it:
<ruleref="category/java/performance.xml/TooFewBranchesForASwitchStatement"><properties><propertyname="minimumNumberCaseForASwitch"value="3"/></properties></rule>Since: PMD 4.2
Priority: Medium (3)
Switch statements are intended to be used to support complex branching behaviour. Using a switch for only a fewcases is ill-advised, since switches are not as easy to understand as if-else statements. In these cases use theif-else statement to increase code readability.
Note: This rule was named TooFewBranchesForASwitchStatement before PMD 7.7.0.
This rule is defined by the following XPath expression:
//(SwitchStatement|SwitchExpression)[count(*)>1](: ignore empty switch blocks :)[(count(*/SwitchLabel/*)+count(*/SwitchLabel[@Default=true()]))<$minimumNumberCaseForASwitch](: do not consider exhaustive switches unless there is a default case :)[@Exhaustive=false()or@DefaultCase=true()]Example(s):
// With a minimumNumberCaseForASwitch of 3publicclassFoo{publicvoidbar(intcondition){switch(condition){case1:instruction;break;default:break;// not enough for a 'switch' stmt, a simple 'if' stmt would have been more appropriate}}}This rule has the following properties:
| Name | Default Value | Description |
|---|---|---|
| minimumNumberCaseForASwitch | 3 | Minimum number of branches for a switch |
Use this rule with the default properties by just referencing it:
<ruleref="category/java/performance.xml/TooFewBranchesForSwitch"/>Use this rule and customize it:
<ruleref="category/java/performance.xml/TooFewBranchesForSwitch"><properties><propertyname="minimumNumberCaseForASwitch"value="3"/></properties></rule>Since: PMD 3.0
Priority: Medium (3)
ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required.
This rule is defined by the following XPath expression:
//ConstructorCall/ClassType[pmd-java:typeIsExactly('java.util.Vector')orpmd-java:typeIsExactly('Vector')]Example(s):
importjava.util.*;publicclassSimpleTestextendsTestCase{publicvoidtestX(){Collectionc1=newVector();Collectionc2=newArrayList();// achieves the same with much better performance}}Use this rule by referencing it:
<ruleref="category/java/performance.xml/UseArrayListInsteadOfVector"/>Since: PMD 3.5
Priority: Medium (3)
Thejava.util.Arrays class has aasList() method that should be used when you want to create a new List froman array of objects. It is faster than executing a loop to copy all the elements of the array one by one.
Note that the result ofArrays.asList() is backed by the specified array,changes in the returned list will result in the array to be modified.For that reason, it is not possible to add new elements to the returned list ofArrays.asList()(UnsupportedOperationException).You must usenew ArrayList<>(Arrays.asList(...)) if that is inconvenient for you (e.g. because of concurrent access).
This rule is defined by the following XPath expression:
//ForStatement[ForInit[LocalVariableDeclaration[PrimitiveType[@Kind='int']][VariableDeclarator[NumericLiteral[@IntLiteral][@Image='0']]]]][*[2]//FieldAccess[@Name='length']/VariableAccess[pmd-java:typeIs("java.lang.Object[]")]]/*[last()]/ExpressionStatement/MethodCall[pmd-java:matchesSig('java.util.List#add(_)')][ArgumentList/ArrayAccess[VariableAccess[@Name=ancestor::ForStatement/ForInit/LocalVariableDeclaration/VariableDeclarator/VariableId/@Name]]]|//ForeachStatement[VariableAccess[pmd-java:typeIs("java.lang.Object[]")]]/*[last()]/ExpressionStatement/MethodCall[pmd-java:matchesSig('java.util.List#add(_)')][ArgumentList[VariableAccess[@Name=ancestor::ForeachStatement/LocalVariableDeclaration/VariableDeclarator/VariableId/@Name]]]Example(s):
publicclassTest{publicvoidfoo(Integer[]ints){// could just use Arrays.asList(ints)List<Integer>l=newArrayList<>(100);for(inti=0;i<ints.length;i++){l.add(ints[i]);}List<Integer>anotherList=newArrayList<>();for(inti=0;i<ints.length;i++){anotherList.add(ints[i].toString());// won't trigger the rule}}}Use this rule by referencing it:
<ruleref="category/java/performance.xml/UseArraysAsList"/>Since: PMD 3.5
Priority: Medium (3)
Use String.indexOf(char) when checking for the index of a single character; it executes faster.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.UseIndexOfCharRule
Example(s):
Strings="hello world";// avoid thisif(s.indexOf("d"){}// instead do thisif(s.indexOf('d'){}Use this rule by referencing it:
<ruleref="category/java/performance.xml/UseIndexOfChar"/>Since: PMD 6.25.0
Priority: Medium (3)
Problem: Use ofFileItem.get()andFileItem.getString()could exhaust memory since they load the entire file into memory.
Solution: UseFileItem.getInputStream()and buffering.
This rule is defined by the following XPath expression:
//MethodCall[@MethodName='get'or@MethodName='getString'][*[pmd-java:typeIs('org.apache.commons.fileupload.FileItem')]]Example(s):
importorg.apache.commons.fileupload.FileItem;publicclassFileStuff{privateStringbad(FileItemfileItem){returnfileItem.getString();}privateInputStreamgood(FileItemfileItem){returnfileItem.getInputStream();}}Use this rule by referencing it:
<ruleref="category/java/performance.xml/UseIOStreamsWithApacheCommonsFileItem"/>Since: PMD 3.8
Priority: Medium (3)
No need to call String.valueOf to append to a string; just use the valueOf() argument directly.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.UselessStringValueOfRule
Example(s):
publicStringconvert(inti){Strings;s="a"+String.valueOf(i);// not requireds="a"+i;// preferred approachreturns;}Use this rule by referencing it:
<ruleref="category/java/performance.xml/UselessStringValueOf"/>Since: PMD 3.1
Priority: Medium (3)
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 StringBuilder orthreadsafe StringBuffer is recommended to avoid this.
This rule is defined by the following Java class:net.sourceforge.pmd.lang.java.rule.performance.UseStringBufferForStringAppendsRule
Example(s):
publicclassFoo{StringinefficientConcatenation(){Stringresult="";for(inti=0;i<10;i++){// warning: this concatenation will create one new StringBuilder per iterationresult+=getStringFromSomeWhere(i);}returnresult;}StringefficientConcatenation(){// better would be to use one StringBuilder for the entire loopStringBuilderresult=newStringBuilder();for(inti=0;i<10;i++){result.append(getStringFromSomeWhere(i));}returnresult.toString();}}Use this rule by referencing it:
<ruleref="category/java/performance.xml/UseStringBufferForStringAppends"/>Since: PMD 3.4
Priority: Medium (3)
Use StringBuffer.length() to determine StringBuffer length rather than using StringBuffer.toString().equals("")or StringBuffer.toString().length() == …
This rule is defined by the following XPath expression:
//MethodCall[pmd-java:matchesSig('_#length()')andMethodCall[pmd-java:matchesSig('java.lang.CharSequence#toString()')]]|(: finds sb.toString().equals(someVar) where var is a final variable initialized with literal "" :)//MethodCall[pmd-java:matchesSig('_#equals(_)')andMethodCall[pmd-java:matchesSig('java.lang.AbstractStringBuilder#toString()')]andArgumentList/VariableAccess[@Name=//VariableDeclarator[StringLiteral[@Image='""']]/VariableId[pmd-java:modifiers()='final']/@Name]]|(: finds sb.toString().equals("") :)//MethodCall[pmd-java:matchesSig('_#equals(_)')andMethodCall[pmd-java:matchesSig('java.lang.AbstractStringBuilder#toString()')]andArgumentList/StringLiteral[@Image='""']]Example(s):
StringBuffersb=newStringBuffer();if(sb.toString().equals("")){}// inefficientif(sb.length()==0){}// preferredUse this rule by referencing it:
<ruleref="category/java/performance.xml/UseStringBufferLength"/>