134

Why in Java you're able to add Strings with the + operator, when String is a class? In theString.java code I did not find any implementation for this operator. Does this concept violate object orientation?

Pooya
  • 4,385
  • 6
  • 45
  • 73
  • 23
    Plus (`+`) operator is language feature of Java. – KV Prajapati Jul 10 '12 at 07:24
  • 19
    It's all compiler's magic. You can't do operator overloading in Java. – Lion Jul 10 '12 at 07:42
  • 19
    I think the weird thing is that String is implemented as a library *outside* the language (in java.lang.String), yet it has specific support *inside* the language. That ain't right. – 13ren Jul 11 '12 at 18:39
  • 1
    possible duplicate of [How does + operator behaves differently with numbers and strings in Java?](http://stackoverflow.com/questions/2955640/how-does-operator-behaves-differently-with-numbers-and-strings-in-java) – Raedwald Oct 02 '14 at 07:12
  • @13ren you are wrong. String is apart of the java.lang class which stands for language - the java lanaguage!!! All classes in this package is special. Notice you dont need to import java.lang to use them. –  Nov 15 '19 at 17:21

7 Answers7

162

Let's look at the following simple expressions in Java

int x=15;
String temp="x = "+x;

The compiler converts "x = "+x; into a StringBuilder internally and uses .append(int) to "add" the integer to the string.

5.1.11. String Conversion

Any type may be converted to type String by string conversion.

A value x of primitive type T is first converted to a reference value as if by giving it as an argument to an appropriate class instance creation expression (§15.9):

  • If T is boolean, then use new Boolean(x).
  • If T is char, then use new Character(x).
  • If T is byte, short, or int, then use new Integer(x).
  • If T is long, then use new Long(x).
  • If T is float, then use new Float(x).
  • If T is double, then use new Double(x).

This reference value is then converted to type String by string conversion.

Now only reference values need to be considered:

  • If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l).
  • Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.

The toString method is defined by the primordial class Object (§4.3.2). Many classes override it, notably Boolean, Character, Integer, Long, Float, Double, and String.

See §5.4 for details of the string conversion context.

15.18.1.

Optimization of String Concatenation : An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate String object. To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.

For primitive types, an implementation may also optimize away the creation of a wrapper object by converting directly from a primitive type to a string.

The optimized version will not actually do a full wrapped String conversion first.

This is a good illustration of an optimized version used by the compiler, albeit without the conversion of a primitive, where you can see the compiler changing things into a StringBuilder in the background:

http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/


This java code:

public static void main(String[] args) {
    String cip = "cip";
    String ciop = "ciop";
    String plus = cip + ciop;
    String build = new StringBuilder(cip).append(ciop).toString();
}

Generates this - see how the two concatenation styles lead to the very same bytecode:

 L0
    LINENUMBER 23 L0
    LDC "cip"
    ASTORE 1
   L1
    LINENUMBER 24 L1
    LDC "ciop"
    ASTORE 2

   // cip + ciop

   L2
    LINENUMBER 25 L2

    NEW java/lang/StringBuilder
    DUP
    ALOAD 1
    INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
    INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;

    ASTORE 3

    // new StringBuilder(cip).append(ciop).toString()

   L3
    LINENUMBER 26 L3

    NEW java/lang/StringBuilder
    DUP
    ALOAD 1
    INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;

    ASTORE 4
   L4
    LINENUMBER 27 L4
    RETURN

Looking at the example above and how the byte code based on the source code in the given example is generated, you will be able to notice that the compiler has internally transformed the following statement

cip+ciop; 

into

new StringBuilder(cip).append(ciop).toString();

In other words, the operator + in string concatenation is effectively a shorthand for the more verbose StringBuilder idiom.

Lion
  • 18,729
  • 22
  • 80
  • 110
  • 3
    Thanks a lot,I'm not familiar with jvm byte codes but generated code for String plus = cip + ciop; and String build = new StringBuilder(cip).append(ciop).toString(); are same. and my question is that is this operation violates object orientation? – Pooya Jul 10 '12 at 07:45
  • 7
    No, it doesn't. Operator overloading (as in C++ and some languages) has some drawbacks and Java designers felt that it's somewhat a confusing concept and omitted it from Java. To me, an object- oriented language must have the prime concepts of inheritance, Polymorphism and encapsulation that Java has. – Lion Jul 10 '12 at 07:48
  • 2
    yes, but I think that this operator has overloaded for String class – Pooya Jul 10 '12 at 07:55
  • 3
    Yes, *operator overloading* is used in Java for the concatenation of the String type however, you cannot define your own operator (as in C++, C# and some other languages). – Lion Jul 10 '12 at 08:01
  • 5
    @Pooya: actually "int / int" vs. "int / float" is *already* operator overloading, so even C has that. What C (and Java) however *don't* have is user-defined operator overloading: the only thing that defines the different ways an operator can be used (in both C and Java) is the language definition (and the distinction is implemented in the compiler). C++ differs in that it allows user-defined operator overloading (which is often referred to as simply "operator overloading"). – Joachim Sauer Jul 10 '12 at 14:32
  • If you want overloading in java I suggest groovy the syntax is identical, it compiles to .class files and interacts very well. You can generally just rename .java to .groovy and it will still work just like it did, but then you can use more syntax. – Bill K Jul 11 '12 at 03:24
  • @Lion One small correction to your comment- in C# you can overload existing operators, but you cannot define your own new operators. – MgSam Jul 15 '12 at 18:06
  • @MgSam:) Thanks for that correction. I'm less familiar with C# (or C++) than Java, sorry. – Lion Jul 16 '12 at 09:16
  • @Lion Please, how did you learn that putting ``The toString method is defined by the primordial class Object (§4.3.2). Many classes override it,.......See §5.4 for details of the string conversion context.`` between ```` and ```` is the way to make this portion of text appear in more little characters ? - I read the Markdown Editing help, the advanced help, and even the official Markdown syntax reference page, but I didn't find any allusion to this way of formatting. – eyquem Nov 23 '13 at 12:39
  • @eyquem : Although it's not mentioned in the help, generally allowing some formatting tags like ``, ``, ``, ``, `
    `, `` etc doesn't cause any security harm like XSS attacks and in general they are allowed by a text editor. I just gave it a try, when I stared questions/answers on this site and they worked. I went nowhere to see whether they are allowed by this text editor or not, just once tried them and found that they were allowed. ha ha ha... :)
    – Lion Nov 23 '13 at 16:16
  • Thank you. I didn't think that `` `` were HTML tags. In fact in the advanced help, in the **Inline HTML** section, we can read : ``If you need to do something that Markdown can't handle, use HTML.`` I wasn't as much astute as you. ah ah ah... :) – eyquem Nov 23 '13 at 16:39
26

It is Java compiler feature which checks the operands of + operator. And based on the operands it generates the byte code:

  • For String, it generates code to concat strings
  • For Numbers, it generates code to add numbers.

This is what the Java spec says:

The operators + and - are called the additive operators. AdditiveExpression: MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpression

The additive operators have the same precedence and are syntactically left associative (they group left-to-right). If the type of either operand of a + operator is String, then the operation is string concatenation.

Otherwise, the type of each of the operands of the + operator must be a type that is convertible (§5.1.8)to a primitive numeric type, or a compile-time error occurs.

In every case, the type of each of the operands of the binary - operator must be a type that is convertible (§5.1.8) to a primitive numeric type, or a compile-time error occurs.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Ramesh PVK
  • 15,200
  • 2
  • 46
  • 50
  • 7
    The quote from the spec isn't relevant to this question at all. – Ernest Friedman-Hill Jul 10 '12 at 13:27
  • This is the extract "If the type of either operand of a + operator is String, then the operation is string concatenation. Otherwise, the type of each of the operands of the + operator must be a type that is convertible (§5.1.8)to a primitive numeric type, or a compile-time error occurs". Can you please tell me why it is not relevant. – Ramesh PVK Jul 10 '12 at 15:48
  • 7
    It doesn't say anything about how it's implemented, which is the question. I think the poster already understand that the feature exists. – Ernest Friedman-Hill Jul 10 '12 at 16:00
14

How String class overrides + operator?

It doesn't. The compiler does it. Strictly speaking, the compiler overloads the + operator for String operands.

user207421
  • 305,947
  • 44
  • 307
  • 483
6

First of all (+) is overloaded not overridden

The Java language provides special support for the string concatenation operator (+), which has been overloaded for Java Strings objects.

  1. If left hand side operand is String it works as concatenation.

  2. If left hand side operand is Integer it works as addition operator

user207421
  • 305,947
  • 44
  • 307
  • 483
Pramod Kumar
  • 7,914
  • 5
  • 28
  • 37
  • 3
    (2) If the left operand is an Integer it is auto-unboxed to `int` and then the normal rules of Java apply. – user207421 Jul 10 '12 at 09:54
  • 2
    The two rules given below the quote are wrong: I believe they should be: two primitives (or unboxable classes) = addition; at least one string = concatenation – mwfearnley Apr 03 '13 at 03:24
4

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.

Jigar Pandya
  • 6,004
  • 2
  • 27
  • 45
4

The meaning of the + operator when applied to String is defined by the language, as everyone has written already. Since you don't seem to find this sufficiently convincing, consider this:

Ints, floats and doubles all have different binary representations, and therefore adding two ints is a different operation, in terms of bit manipulation, than adding two floats: For ints you can add bit by bit, carrying a bit and checking for overflow; for floats you must deal with the mantissas and exponents separately.

So, in principle, "addition" depends on the nature of the objects being "added". Java defines it for Strings as well as ints and floats (longs, doubles, ...)

alexis
  • 48,685
  • 16
  • 101
  • 161
3

The + operator is usually replaced by a StringBuilder at compile time. Check this answer for more details on that matter.

Community
  • 1
  • 1
Scorpio
  • 2,309
  • 1
  • 27
  • 45
  • If this is the case, is there any reason why StringBuilder exists at all for public use ? Are there any cases where `+` operator is not replaced by `StringBuilder` ? – Cemre Mengü Apr 10 '13 at 16:38
  • 2
    The question you want to ask is "why does the + operator exist at all for public use?", because thats the abomination here. As for your other question, I do not know it exactly, but I'd guess there is no such case. – Scorpio Apr 12 '13 at 05:51
  • Compiler might use concat() instead, if there are just two elements. Also compiler fails to replace concat() with StringBuilder( or uses multiple StringBuilders and appends them together) when programmer is building string in long nested/looped code - using single, explicit StringBuilder will be better for performance. – user158037 Aug 27 '15 at 12:06