Java can't do operator overloading, but + works okay for String and Integer and some other classes. How is this possible?
update:
Why does this work?
Integer i = 4;
Integer p = 5;
System.out.println(i*p); // prints 20
+ is not an example of operator overloading. + is built into the language as a concatentation operator and an arithmetic-addition operator.
What this means is that a person writing a program with Java cannot overload operators, but as far as the grammar of the Java language is concerned, + is defined as a concatenation and an addition operator.
EDIT
It works for other classes such as Integer and Double because of autoboxing.
If you take a look at the bytecode of a Java program that performs string concatenation, you'll see that it creates StringBuilder and uses the append() method. The Java compiler sees the + operator and realizes that the operands are strings and not primitive types (like int).
If you look at the bytecode of a program that does integer addition, you will see that it uses the iadd instruction to perform integer addition. This is because the compiler realizes that the operands to the + operation are integers.
As far as doing something like Integer i = 4, the bytecode will show that you're actually doing Integer i = Integer.valueOf(4). This is called autoboxing. Later on, when you do something like i + p, where both i and p are of type Integer, the generated bytecode will show that you're doing i.intValue() + p.intValue(), where the return types of both methods are int (the actual bytecode instruction again, is iadd).
This is why + works Integer even though they are not actual primitive types.
It works for primitive wrappers like Integer because of autoboxing.
It works for String because that's a special case for concatenating strings:
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, see Gosling, Joy, and Steele, The Java Language Specification.
+ is a built-in operation. It's an exception, not a rule.
Java doesn't allow custom operator overloading, but the compiler can still be told by the compiler developer that String1 + String2 == String1String2, and to substitute the proper concatenation method call for the + operator.
The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings.
String s = "string 1" + "string 2";
What actually is execute is
(new StringBuilder()).append("string 1").append("string 2").toString()
As #yan said, this is the exception, not the rule. Strings have a special status in Java. There's a whole subsection of the Java Language Specification devoted to + in its role as the string concatenation operator: §15.18.1.
Regarding your update, that's another special case. Java is sometimes, depending on the case, smart enough to convert things that are not Strings into Strings when Strings are needed. One of these special cases is the one you described, where primitives are showing up in a place that needs a String. The primitives are first converted to their reference types — Integer, Double, &c. — and then into Strings via the toString() method.
Another special case is when one String and one non-String are being combined with the string concatenation operator +, as described in JLS §5.4 — String Conversion.
For completeness: + in its more common "adding numbers together" role is described in the other part of of §15.18, §15.18.2 — Additive Operators (+ and -) for Numeric Types.
Related
I'm learning to code on Codecademy and keep coming up with a concatenating issue.
For example, when I wrote:
System.out.println(lemonadeStand + cookieShop);
I got back the error:
Store.java:32: error: bad operand types for binary operator '+'
System.out.println(lemonadeStand + cookieShop);
But when I wrote:
System.out.println(lemonadeStand);
System.out.println(cookieShop);
The code worked. Can someone tell me why doesn't the first one work? (And thanks)
---edit---
Thanks for all the help everyone! This was my first time posting a question here and I'm amazed at how kind and helpful the community is!
please before concatening two variable you must verify they are
same type
or try System.out.println(first + " " + second);
Because the single variables alone cause a call to their .toString() method. When you add the operand between two non-string variables, it's not sure exactly what you mean. You will sometimes see this ...
System.out.println(lemonadeStand + cookieShop + "");
That + "" in there confirms this is all boiling down to a string (if that's any way to explain it technically to you.)
What would also work is ...
System.out.println(lemonadeStand.toString() + cookieShop);
or...
System.out.println(String.valueOf(lemonadeStand) + cookieShop);
It depends what those variables actually are. But if they aren't strings ... it's ambiguous as to what you are telling it to do ... add them together maybe?
Placing a single + "" somewhere in there is a common way to force it all to be interpreted as a string concatenation.
Hope that explains it in non technical terms.
Too broad...
But, a method accepting a String needs a String as a parameter.
The println is overloaded in PrintStream class so it accepts all of the primitive types, String and the Object type.
bad operand types for binary operator '+'
The point is in "binary" operator. The plus "+" is normally considered as arithmentic (a binary) operator between two numbers. And secondly, the "+" COULD BE CONSIDERED as String concatenation operator.
[Side note, Java doesn't allow overloading of operators]
Binary, therefore arithmetic, logical and bitwise operators expects the defined types for them selfs.
In the case of "+" operator, it is most ofen considered as addition operator.
Expressions with numeric types are being automatically promoted to larger primitive types if needed.
So again, the call to a + b is only possible with numeric or String operands. If one of a or b is not numeric or String operand, the error will be thrown.
It's the implementations of println/print methods of PrintStream class that tries to get a default result of toString method for given parameter.
The System.out.print(...) is kind of combination of objects and calls. The System is static object representing a System in runtime environment, the out represents standard output stream for a current thread and print is a method called on that out PrintStream. There are several different streams, just for example an err which is standard error output stream.
The standard print or println method is overloaded to accept a Object type where those methods tries to call the toString method on given Object as a parameter. But it cannot evaluate the given expression with + operand, if the whole expression is not evaluated to Number or String.
Cutting to the chase,
the "+" at first works as arithmetic operator, if next operator is a String it converts the rest of expression to String.
When "+" has two object or incompatibile operators, it cannot determine how the operands should be handled. How it could add list to an array or simply true + true? For the second (true + true) the logical && must be used.
In your case, when you tried to + between the different types, the println gave you an error, because the "+" is only able to concatenate Strings or sum both of the opearands which inherits from Number class.
Answer from #Moyebang is kind of good, because the expression given as parameter in printnl method evaluates to String type. The answer from #Lotsa isn't very good because the operands are evaluated from left to right, so if the operands before + are incompatible, the program would throw an error (the second part of an answer is ok).
Such expressions at first are evaluated in their compile time.
They are evaluaded on standard basics from left to right:
System.out.println(1 + 1 + ""); //this gives 2
System.out.println("" + 1 + 1); //this gives 11
System.out.println(1 + "" + new ArrayList<>()); //this gives 1[]
System.out.println(new ArrayList<>() + "" + 1); //this gives []1
System.out.println(new ArrayList<>() + 1 + ""); //and this gives an error
So, from left the mathematical equasions are being evaluated, when it's a String the others are being addeded to that String. The last shows an error because at first the ArrayList object is being added to "1", where there's no common approach on how to add the List to an object.
This question already has answers here:
String valueOf vs concatenation with empty string
(10 answers)
Closed 7 years ago.
I've had a few people tell me that things like this are super lazy:
int val = 5;
System.out.println("" + val);
String myStr = "" + val;
Why is this better than String.valueOf(val)? Isn't it doing the exact same thing under the hood?
It's not really "better", just shorter, making it easier to read and type. There is (virtually) no ther difference, even though a real purist might, probably, say, this is actually worse, because (at least, in the absence of optimization), this creates an intermediate StringBuilder object, that is then appended a character before being converted into a String, so, this may be spending more ticks, than .valueOf.
From JLS:
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.
This question already has answers here:
StringBuilder/StringBuffer vs. "+" Operator
(4 answers)
StringBuilder vs String concatenation in toString() in Java
(20 answers)
Closed 8 years ago.
In the past, I have been lead to believe that you should use StringBuilder and append(String) when building a string with variables, as opposed to string += split[i]. In what cases is this accurate? I ask because normally, if I was to write the following:
String[] split = args; // command line arguments or whatever
String myString = "";
for (int i = 0; i < split.length; i++) {
myString += split[i];
}
I am told by my IDE that it should be converted to use a StringBuilder instead. However, writing something like this:
StringBuilder build = new StringBuilder();
build.append("the ").append(build.toString()).append(" is bad").append(randomvar);
build.toString();
IntelliJ actually lists as a performance issue using a StringBuilder when I should be using a String. The fact that it's listed as a performance issue would indicate it could actually cause problems as opposed to just being a tiny bit slower.
I did notice that the first example is a loop and the second isn't - is a StringBuilder recommended for lots of concatenations but normal concatenation is better for non-looping situations (this also means in a loop the operator += would be used, whereas outside of a loop it could be "the " + build.toString() + " is bad" + randomVar - is += the problem as opposed to +?)
String concatenations are converted into calls to StringBuilder.append() behind the scenes.
String literal concatenations are (or at least can be) converted to individual String literals.
You're presumably using a String variable (not just two literals) inside the loop, so Java can't just replace that with a literal; it has to use a StringBuilder. That's why doing String concatenations in a loop should be done using a single StringBuilder, otherwise Java ends up creating another instance of StringBuilder every time the loop iterates.
On the other hand, something like this:
String animals = "cats " + "dogs " + "lizards ";
Will (or can be) replaced (by Java, not you) with a single String literal, so using a StringBuilder is actually counter-productive.
Beginning in java 1.5, the String + operator is translated into calls to StringBuilder.
In your example, the loop should be slower because the + operator creates a new StringBuilder instance each time through the loop.
The compiler will actually turn them both into the same form before compiling so neither will result in any performance difference. In this scenario you want to go with the shortest and most readable method available to you.
"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."
Source: http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html#15.18.1.2
For little concats you can use the + operator with none issue. StringBuffer is indicated when we have large strings to be concatened, so with this class you can save memory and processor's time as well.
You can make a test trying to concat 1 million of words using + operator, and run the same teste using StringBuffer to see the different by yourself.
This question already has answers here:
How does the String class override the + operator?
(7 answers)
Closed 9 years ago.
Can any one tell me the exact implementation of '+' operator of String in Java.
As I know this is concat operator to concat two string even then since String is a class then where is implementation of this operator and how it works?
The implementation is compiler-specific, although it usually just ends up creating a StringBuffer or StringBuilder behind the scenes, and appends to it. Note that it has special treatment for efficiency, so that x + y + z can be compiled as something like
new StringBuilder().append(x).append(y).append(z).toString();
... and also to perform compile-time concatenation of constant string expressions.
You can see the operator described in JLS section 15.18.1, but that doesn't mandate any particular implementation.
To see what your particular compiler does, simply compile some code you're interested in and then use javap -c to look at the bytecode it generates.
String + may be optimised away by the compiler. If it is not it is the same as
a + b
becomes on most JVMs today (older versions used StringBuffer)
new StringBuilder().append(a).append(b).toString();
So StringBuilder.append() is what you want.
What is the style recommendation for the Java string concatenation operator "+"?
Edit: Specifically, should it be used or not?
Thinking in Java (Eckel) says that the overloaded + operator is implemented using StringBuilder (although not all compilers may be supporting this as per alphazero's answer) and thus multiple String objects and the associated memory use and garbage collection are avoided. Given this, I would answer my own question by saying that the + operator is probably fine, style-wise. The only caveat is that the + is the only instance of overloading in the language and that exceptionalism might count as a minor reason not to use it. In retrospect, the advantage of terseness is pretty significant in some situations and that has got to count for a lot of style.
As long as your team members are comfortable with it.
Because there is no "correct" coding style. But I agree that you should always use white-spaces between strings and operator for better readability.
Following Java's coding conventions Strings should be concatenated like:
String str = "Long text line "
+ "more long text.";
Make sure the '+' operator always begins the next line.
https://www.oracle.com/technetwork/java/javase/documentation/codeconventions-136091.html#248
It is perfectly fine to use the '+' operator for String concatenation, there are different libraries that provide other structure for it, but for me it is the most simple way.
Hope this helps!
Happy coding,
Brady
Is this what you meant?
"string1" + "string"
or, if you have long lines
"a really long string....." +
"another really long string......" +
"ditto once again" +
"the last one, I promise"
If you have the time to format this right, then:
"a really long string....." +
"another really long string......" +
"ditto once again" +
"the last one, I promise"
Basically, every time you use the + operator, you should use it with at least one whitespace before and after. If you're using it when concatenating long strings, put it at the end of the line.
The overall recommendation is not to use this form (at all) if performance is of concern, and to instead use StringBuilder or StringBuffer (per your threading model). The reason is simply this: Strings in java are immutable and the '+' operator will create many intermediary String objects when processing expressions of form S1 + S2 + ... + Sn.
[Edit: Optimization of String Concatenation]