In matters of style (and this is a matter of style; run a micro-benchmark to prove and quantify run-time performance differences) I would follow these rules:
- if your project has a style guide that recommends one particular choice, follow the style guide
- if it has existing code that consistently follows one choice, follow that choice
- if neither applies, make a choice and stick to it
The source for the JDK is freely available. In Java 8, I count 276 files with one or more occurrences of "" +
(and in the ones that I looked at, numbers often followed). Of course, there are >3k files with calls to .toString
, and I have not looked at .valueOf
at all, so this is hardly conclusive. Therefore, use of "" +
number-to-string conversion does not appear to be uncommon or frowned upon in well-written Java code.
Not that good Java developers would concatenate strings inside loops; a frequent use seems to be generating error messages for exceptions.
Oracle's ancient Java style guide, and the more recent ones by Google and Spring do not appear to have a say on the matter. Therefore, I feel that there is no right answer, and if coding together on a project, and you care enough about this, you should apply Rule 3: iron out a compromise, document it in your project's style guide, and stick to it.
On a personal note, I find "" + o
easier to read than many of the alternatives, as syntactic sugar for a call to toString()
that works regardless of the type of o
(and even when o
is null).
I actually tried this out using caliper on JDK 11, and results show minimal run-time difference, and no memory or object-count difference, when performing 1k int-to-string conversions by these 3 methods:
t (ms) method
12,30 "" + j
12,57 Integer.toString(j)
12.58 String.valueOf(j)
Code to reproduce:
package org.example;
import com.google.caliper.BeforeExperiment;
import com.google.caliper.Benchmark;
import com.google.caliper.Param;
import com.google.caliper.runner.CaliperMain;
public class Main {
@Param({"10", "100", "1000"})
int size;
private String[] output;
@BeforeExperiment
void setUp() {
output = new String[size];
}
@Benchmark void quote(int reps) {
for (int i = 0; i < reps; i++) {
for (int j = 0; j < size; j++) {
output[j] = "" + j;
}
}
}
@Benchmark void toString(int reps) {
for (int i = 0; i < reps; i++) {
for (int j = 0; j < size; j++) {
output[j] = Integer.toString(j);
}
}
}
@Benchmark void valueOf(int reps) {
for (int i = 0; i < reps; i++) {
for (int j = 0; j < size; j++) {
output[j] = String.valueOf(j);
}
}
}
public static void main(String[] args) {
CaliperMain.main(Main.class, args);
}
}