Is concatenating with an empty string to do a string conversion really that bad?
Asked Answered
V

9

45

Let's say I have two char variables, and later on I want to concatenate them into a string. This is how I would do it:

char c1, c2;
// ...

String s = "" + c1 + c2;

I've seen people who say that the "" + "trick" is "ugly", etc, and that you should use String.valueOf or Character.toString instead. I prefer this construct because:

  • I prefer using language feature instead of API call if possible
    • In general, isn't the language usually more stable than the API?
    • If language feature only hides API call, then even stronger reason to prefer it!
      • More abstract! Hiding is good!
  • I like that the c1 and c2 are visually on the same level
    • String.valueOf(c1) + c2 suggests something is special about c1
  • It's shorter.

Is there really a good argument why String.valueOf or Character.toString is preferrable to "" +?


Trivia: in java.lang.AssertionError, the following line appears 7 times, each with a different type:

    this("" + detailMessage);
Vidovik answered 24/3, 2010 at 9:23 Comment(5)
Of course String.valueOf(c1) + c2 would be weird, if you go down that route you'd write String.valueOf(c1) + String.valueOf(c2)Bummalo
@NomeN: you could write new String(new char[] {c1, c2})Bruner
ad Trivia: the Java SE core libraries are not exactly a fountain of good coding style, that's well-known ;-)Bruner
@Joachim Sauer yeah that's another way to do it. I just wanted to point out that it is a little nonsensical to convert one but not the other. It would, as the OP rightly said, wrongly suggest that something special is going on.Bummalo
Look here for a related question: #1573208Commando
A
29

Your arguments are good; this is one of the more expressive areas of the Java language, and the "" + idiom seems well entrenched, as you discovered.

See String concatenation in the JLS. An expression like

"" + c1 + c2

is equivalent to

new StringBuffer().append(new Character(c1).toString())
                  .append(new Character(c2).toString()).toString()

except that all of the intermediate objects are not necessary (so efficiency is not a motive). The spec says that an implementation can use the StringBuffer or not. Since this feature is built into the language, I see no reason to use the more verbose form, especially in an already verbose language.

Almanza answered 24/3, 2010 at 9:35 Comment(1)
Actually, no. The JLS explains it this way, but the compiler implements it differently. The Eclipse compiler produces bytecode equivalent to new StringBuilder().append(c1).append(c2).toString() The javac compiler (1.5) produces bytecode equivalent to new StringBuilder().append("").append(c1).append(c2).toString()Cypro
B
22

The problem with that construct is that it usually doesn't express the intent.

It represents concatenation of a String with another value, but concatenation is not usually the goal of this line.

In the specific case that you demonstrated, concatenation is actually the goal, so this code does express the intent.

In the more common use of this approach (String s = "" + intValue;), the concatentation is merely a tolerated side-effect, while the conversion of intValue is the actual goal. And a simple String.valueOf(intValue) expresses that intent much clearer.

Bruner answered 24/3, 2010 at 9:46 Comment(9)
I don't think so. "" + x is extremely common, the intent should be clear.Rickyrico
@mafutrct: if the intent is only clear when you've seen that exact construct many times before, then it isn't clear as such. It only proves that pattern recognition works.Bruner
@polygenelubricants: fair enough!Bruner
I would argue that nearly every java programmer has seen that exact construct many times before, as it's probably one of the first things they learn. For the ones who haven't, they're definitely going to see it many times in the future and will probably catch on quick.Michaelemichaelina
@Chris: don't underestimate the number of inexperienced developers out there and how many of them have to maintain existing code.Bruner
@Chris: let me try to rephrase your argument: "It's not ugly, because it's common." That doesn't sound right to me.Bruner
I didn't say it wasn't ugly. More like "It's incredibly common and probably not going to go away."Michaelemichaelina
@Chris: then I misread your comment, sorry. But does that mean that it should be used?Bruner
I think you've already given a very suitable answer to that question :)Michaelemichaelina
P
6

I prefer using String.valueOf for single conversions - but in your case you really want concatenation.

However, I would suggest that this version would remove all potential ambiguity:

String s = c1 + "" + c2;

That way there's no possibility, however remote, of someone considering whether c1 and c2 will be added together before the concatenation.

Pow answered 20/4, 2010 at 11:52 Comment(0)
F
3

What about

new String(new char[] {a, b})

and if you do it alot you could create a class "Strings" with:

public static String valueOf(char... chars) {
    return new String(chars);
}

Your line would then read

String s = Strings.valueOf(a, b);

Nice and short.

Edited

A better name might be:

String s = Chars.asString(a, b);
Francyne answered 24/3, 2010 at 14:56 Comment(5)
Should also be very fast, as the only thing that has to be done is an array copy which is quite fast.Francyne
-1 nobody Can tell what this does without looking at the method called. Please refactor!Ddt
@Thorbjørn: Any suggestions? Constructive criticism is always welcome.Francyne
I would probably name the class CharHelper (CharUtils is another candidate) and the method charsToString, making the line String s = CharHelper.charsToString(a, b)Ddt
A javadoc comment would be sufficient in my opinion. There are a lot of methods in the jdk which are useless without description. Having a method in a class called Strings which takes a char array and produces a String seems relatively straight forward to me. You suggestion is too verbose. Chars.asString(char... chars) might be a good alternative.Francyne
U
2

I think that in "" + var the + is actually overloaded to make the conversion:

The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method. String conversions are implemented through the method toString, defined by Object and inherited by all classes in Java. For additional information on string concatenation and conversion

So no difference and no problem from a technical point of view.

Form a readability point of view - it's a matter of personal preference or agreed coding style within the team.

Utopianism answered 24/3, 2010 at 9:25 Comment(1)
I just added the [coding-style] tag to the question; that's what this is mostly about.Vidovik
R
2

In my opinion, "" + x is very readable, short, and precise to the point. I'd prefer it to longer constructs like String.valueOf. The behavior is well defined and it's so commonly in use that I find it hard to call it a hack at all.

The only thing I'd be slightly worried about is performance - and am very positive that it does not matter usually (even though I did not measure or look at the binary). There is also a fair chance that this kind of concat is optimized away, since it should be easy to detect it (this is just a guess though).

Rickyrico answered 24/3, 2010 at 9:47 Comment(2)
it matters greatly if your code is run hundreds of thousands of times in a loop.Izawa
Nobody would use this in a loop - in loops you're always using the most well known performant code. In 99% of all cases, it's not a problem. Readability in the general case is far more important, imo.Rickyrico
M
2

The "" + var style has one very big issue in my opinion. It just uses the toString method of the var. So if you change the type of var to something else, you will not get an exception. A nice example I just encountered was that the type was changed from int to Optional<Integer>. The code still compiles fine, but you get a completely different result.

Michaelemichaelina answered 31/3, 2015 at 8:24 Comment(0)
D
1

Unless your app needs every ounce of performance, write the code that's quicker to write and easier to read. "" + is a slower-to-execute syntax, but it certainly seems easier to read every time I've used it.

Diep answered 24/3, 2010 at 13:41 Comment(0)
R
0

The best way to know is to compile / decompile your code, I used Jad http://en.wikipedia.org/wiki/JAD_(JAva_Decompiler) for that, you will see that your expression was converted into

String s = (new StringBuilder()).append("").append(ci).append(c2).toString();

As you can see javac actually included append("") call, but its cost is negligible, noting is appended to internal StringBuilder buffer, you can check StringBuilder's source

Rufena answered 6/12, 2012 at 9:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.