String Concatenation - valueOf or not - java

So I just perused for a while, all the different questions on here about .valueOf with strings, but they all seem to be about conversions. Comparing .valueOf to just + "".
I want to know if it is worth it or at all necessary to use .valueOf if it is a concatenation.
Example:
LOGGER.info("Final Score: " + String.valueOf(Math.round(finalScore * 100)) + "%");
VS
LOGGER.info("Final Score: " + Math.round(finalScore * 100) + "%");
It seems as though using String.valueOf is unnecessary if you have actual strings to go along with it. I understand it may be better to use .valueOf if you were just converting it and intended to use an empty string.

When we concatenate strings, the compiler actually translates it to StringBuffer.append().
The underlying implementations for StringBuffer.append(int) and String.valueOf(int) both eventually end up calling Integer.getChars(int,int,char[]) except that in case of String.valueOf(), there is a call to Integer.toString(int) first.
To conclude, for the given scenario, directly concatenating would be the way to go. But if you intend to be conscious about memory, then use string-builder to concatenate values first and then log it.

The source code for String#valueOf(Object) looks like this:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
So the only difference between valueOf and toString is that valueOf is null-safe. So let's see which one is used if we concatenate a string and an object.
Object foo = null;
System.out.println("foo " + foo); //foo null, no exception thrown
System.out.println("foo " + String.valueOf(foo)); //foo null, no exception thrown
So it looks like there's no difference whatsoever between concatenation and using valueOf in this context.

you are correct. When you are combining strings and other datatypes, the valueOf is not necessary. For only an int, I think the valueOf works, but anecdotally, the 2nd example is a lot more common
#Test
public void testStringValueOF(){
int num = 123;
// this works...
String test = String.valueOf(num);
// but this is more common
String test2 = "" + num;
}

Related

Surround string with another string

I there any utils method in Java that would enable me to surround a string with another string? Something like:
surround("hello","%");
which would return "%hello%"
I need just one method so the code would be nicer then adding prefix and suffix. Also I don't want to have a custom utils class if it's not necessary.
String.format can be used for this purpose:
String s = String.format("%%%s%%", "hello");
No but you can always create a method to do this:
public String surround(String str, String surroundingStr) {
StringBuffer buffer = new StringBuffer();
buffer.append(surroundingStr).append(str).append(surroundingStr);
return buffer.toString();
}
You have another method of doing it but Do not do this if you want better performance:-
public String surround(String str, String surroundingStr){
return surroundingStr + str + surroundingStr;
}
Why not use the second method?
As we all know, Strings in Java are immutable. When you concatinate strings thrice, it creates two new string objects apart from your original strings str and surroundingStr. And so a total of 4 string objects are created:
1. str
2. surroundingStr
3. surroundingStr + str
4. (surroundingStr + str) + surroundingStr
And creating of objects do take time. So for long run, the second method will downgrade your performance in terms of space and time. So it's your choice what method is to be used.
Though this is not the case after java 1.4
as concatinating strings with + operator uses StringBuffer in the background. So using the second method is not a problem if your Java version is 1.4 or above. But still, if you wanna concatinate strings is a loop, be careful.
My suggestion:
Either use StringBuffer of StringBuilder.
Not that i know of, but as already commented, its a single line piece of code that you could write yourself.
private String SurroundWord(String word, String surround){
return surround + word + surround;
}
Do note that this will return a New String object and not edit the original string.
Create a new method:
public String surround(String s, String surr){
return surr+s+surr;
}
Tested the following and returns %hello%
public static void main (String[] args) throws java.lang.Exception
{
System.out.println(surround("hello", "%"));
}
public static String surround(String s, String sign) {
return sign + s + sign;
}
StringUtils.wrap(str,wrapWith) is what you are looking for.
If apache common utils is already a part of dependency, then you can use it. Otherwise as others already mentioned. It's better to add to your base. Not a big deal
https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/StringUtils.java

Clarification about the toString method within an ADT class

This is the modified toString function within the Complex ADT class that i'm trying to implement (My doubt is only regarding this function so I havent included the private variables declared before and the other functions) :
class ComplexCart implements Complex{
public String toString(){
if(image == 0) return (real + "");
}
}
Why can't we write the following?
if(imag == 0) return(real);
Why do we need to add the additional "" ?
since the return type is String, and real is integer type. alternatively you can use real.toString()
Since real is int type where as toString() method expects String to return.So you need add "";
+ is String concatenation operator here.
public String toString(){
if(image == 0) return (real + "");
}
In the above code if real is not of type String it's compile time error.
if it is of type String.No errorrs occures.
To make real as string you are writing real + "".
Then , Immediate question is Then how it's working with + "" ??
Here the Docs of String
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.
As a side note:
concatenating with String is a bad idea.There are some identical and better ways to do it.
1)Integer.toString(intval);
2)String.valueOf(intval);
It's because you have to return a String from toString(), and presumably real is not a String. real + "" performs string concatenation (converting real to a String and concatenating it with the empty string; see JLS ยง15.18.1) and results in a String, which is why you can validly return it.
Note that you should consider using something like Integer.toString(real) over real + "" (see Integer.toString()).

Why do I get different results when comparing strings after using different concatenation in Java?

i was working on the basic java program and i found verry funny thing which i am sharing with you. foo() gives output (s==s1) = false and bar gives (s==s1) = true.
I want to know why this happens.
public class StringTest
{
public static void main(String[] args){
foo();
bar();
}
public static void foo(){
String s = "str4";
String s1 = "str" + s.length();
System.out.println("(s==s1) = " + (s1==s));
}
public static void bar(){
String s = "str4";
String s1 = "str" + "4";
System.out.println("(s==s1) = " + (s1==s));
}
}
In the latter case, the compiler optimizes the string concatenation. As this can be done at compile time, both reference the same constant string object.
In the former case, the length() call can't be optimized during compile time. At runtime, a new string object is created, which is not identical to the string constant (but equal to it)
The string catenation in bar() can be done at compile time, because it's an expression composed of nothing but compile-time constants. Although the length of the String s is obviously known at compile time, the compiler doesn't know that length() returns that known value, so it won't be used as a constant.
When you write a line of code like this:
String s1 = "str" + "4";
then the compiler is smart enough to optimize this to:
String s1 = "str4";
Literal strings in Java are managed in a string pool. When you have two literal strings that have the same content (such as s and s1 in your second example), then just one String object will be created which will be shared by the two variables.
The == operator in Java checks if two variables refer to the same object. Since there is only one String object in the second example, s == s1 will be true.
String s1 = "str" + s.length();
String s1 = "str" + "4";
In first case s.length() will return a value of type int, In second case The type is String
Even though the number is 4 in both the cases but types are not the same :)
It probably has to do with the fact that foo() is probably creating an new String instance in s.length()(.toString()), where as bar() is just concatenating a constant. I don't know the nitty gritty of it, but my gut tells me it in that direction
If I needed to guess I would say that the java compiler performs some optimization onto bar(). At compiletime it is clear that "str" + "4" can be replaced by "str4" which (since Strings are immutable objects) is indeed the very same object as "str4"-String used for the s-initialization.
Within foo() the optimization is not that streight forward. In general the value s1-variable cannot be predicted very easily (indeed this example is quite streight forward). So the java compiler will produce two different variables for s and s1.
The "==" operator does not compare the value of the Strings! It checks whether these are the same Objects. To compare the values of the Strings use the "equals" method like this:
String s = "str4";
String s1 = "str" + s.length();
System.out.println("(s==s1) = " + (s1.equals(s2));
You should try playing with intern method of String class. Java keeps something like dictionary where all different strings are stored. When you create a string object which can be evaluated at compile time, Java searches it in its dictionary. If it founds the string, it stores only a reference to this string (which is actually returned by intern method).
You should notice that:
"str4" == ("str" + "str4".length()) returns false, but
"str4" == ("str" + "str4".length()).intern() returns true, because the only "wrapper" is a different object.

Java toString Method (objects)

class Position {
private double x,y;
private int id;
public String toString(Position a){
String words ="(" + a.x + "," +a.y + ")";
return words;
So I'm getting a memory address returned here. What am I doing wrong? I want to get the actual values of x and y that were set using setters. I also have getters, and I tried instead of putting a.x putting getX(), but that still give me another memory address. What am I doing wrong?
Try:
public String toString(){
The code you have is adding a new method, instead of overriding the existing parameterless toString method of Object. That means the old method is still the one being called, and it gives the output you're seeing.
You're not actually overriding toString; rather, you're overloading it by defining a method with the same name but which expects different arguments. You don't pass a Position to toString; it should refer the current instance.
As a complement to other posts, why do you think you need to pass Position's reference to the method toString(), anyway. After all, the method exist in the same class, Position. You can use the variable/properties directly without any reference like this.
public String toString(){
return "(" + x + "," + y + ")";
}
Or in case you like to specifically have a reference then you can do it like this,
public String toString(){
return "(" + this.x + "," + this.y + ")";
}
I made the method one liner after refactoring.
In case you are interested in knowing which version folks like more, please refer to here, when to use this. And here is the tutorial/explanation on how overriding works in Java.
Since it is a homework, I would ask you step through a debugger. Your method is not called even though you expect it do so. ( toString() and toString(Someobject ) are different.

Dynamic if statement evaluation problem with string comparison

I tried the example given in this thread
to create if statement dynamically using BeanShell. But it is not working fine. Instead of using "age" variable as integer, i have used string in the below example. I am getting "fail" as answer instead of "success".
Can anyone help me?
/*
To change this template, choose Tools | Templates
and open the template in the editor.
*/
import java.lang.reflect.*;
import bsh.Interpreter;
public class Main {
public static String d;
public static void main(String args[])
{
try {
String age = "30";
String cond = "age==30";
Interpreter i = new Interpreter();
i.set("age", age);
System.out.println(" sss" + i.get("age"));
if((Boolean)i.eval(cond)) {
System.out.println("success");
} else {
System.out.println("fail");
}
}
catch (Throwable e) {
System.err.println(e);
}
}
}
Thanks,
Mani
You have to choose either numeric comparison or String comparison. This requires using a compatible condition and type for age.
Numeric:
int age = 30;
String cond = "age==30";
String:
String age = "30";
String cond = "age.equals(\"30\")";
When you compare two objects with the == operator, you're comparing two references. You're essentially asking whether two different names refer to the same object in memory.
To compare the actual values of objects, you need to use the equals() method. This is something that's very important to understand about Java.
#Matthew Flaschen is correct. As an aside, you can simplify your output as follows:
System.out.println(cond + " is " + i.eval(cond));
which produces
age == 30 is true
You are using == to compare string types. Try using age.equals("30") instead.
EDIT: to show it working
If you use this as the definition of cond:
String cond = "age.equals(\"30\")";
Output:
sss30
success
In response to the question about using =="30" instead, here is the answer to that:
If your String age is interned, because it is a compile-time constant for example, then it could be true.
final String age = "30";
However if you explicitly new the String or it is otherwise not interned, then it will be false.
String age = new String("30");
You can run both examples to see this in effect. Possibly - you may get fail for both.
Now, just because interning exists doesn't mean one should ever rely on it for comparing String types. The == operator should only be used to compare primitives to each other, and to compare reference types to see if they point to the same object, so for reference types we could say it is seeing if two objects are identical instead of equal.
Sometimes through the magic of the JVM and JDK, String and other primitive wrappers like Integer may be comparable with ==, but the situations for this are limited and not reliable.
The string compare with "==" in the bsh interpreter is not working like expected.
It is working like that: (copied from the link bellow)
Beanshell handles '==' like java and not e.g. like JavaScript. That means you've got to use "equals" to compare instances.
bsh % "abc" == "abc"; => true
bsh % "abc" == new String("abc"); => false
bsh % "abc".equals("abc"); => true
bsh % "abc".equals(new String("abc")); => true
further information here: https://code.google.com/p/beanshell2/issues/detail?id=86
So you have to use the ".equal()", or compile your own bsh version, like i did it.
(read the complete issue above)

Categories

Resources