String.valueOf(someVar) vs ("" + someVar) [duplicate] - java

This question already has answers here:
String valueOf vs concatenation with empty string
(10 answers)
Closed 5 years ago.
I want to know the difference in two approaches. There are some old codes on which I'm working now, where they are setting primitive values to a String value by concatenating with an empty String "".
obj.setSomeString("" + primitiveVariable);
But in this link Size of empty Java String it says that If you're creating a separate empty string for each instance, then obviously that will take more memory.
So I thought of using valueOf method in String class. I checked the documentation String.valueOf() it says If the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.
So which one is the better way
obj.setSomeString("" + primitiveVariable);
obj.setSomeString(String.valueOf(primitiveVariable));
The above described process of is done within a List iteration which is having a size of more than 600, and is expected to increase in future.

When you do "" that is not going to create an Object. It is going to create a String literal. There is a differenc(How can a string be initialized using " "?) actually.
Coming to your actual question,
From String concatenation docs
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.
So unnecissarly you are creating StringBuilder object and then that is giving another String object.
However valueOf directly give you a String object. Just go for it.
Besides the performance, just think generally. Why you concatenating with empty string, when actually you want to convert the int to String :)

Q. So which one is the better way
A. obj.setSomeString(String.valueOf(primitiveVariable)) is usually the better way. It's neater and more domestic. This prints the value of primitiveVariable as a String, whereas the other prints it as an int value. The second way is more of a "hack," and less organized.
The other way to do it is to use Integer.toString(primitiveVariable), which is basically the same as String.valueOf.
Also look at this post and this one too

Related

How many Strings are formed? [duplicate]

This question already has answers here:
How many string objects will be created in memory? [duplicate]
(4 answers)
Closed 3 days ago.
String a="hello";
String b=a+"Bye";
How many Strings are formed?
From my understanding of Java.
What happens in this code is:
String a="hello"; // hello is created in string pool
String b=a+"bye"; // new StringBuilder(a).append("bye")
So totally 2 strings are to be created, right?
1.Hello
2.HelloBye (In the Heap)
Or does Java create 3?
1.Hello
2.Bye
3.HelloBye
If this is the case, does append method create the appending strings in the string pool?
String a = "hello";
JVM will create one string in the string pool. (FIRST STRING IN POOL)
Now, here comes the tricky part>
b = a + "bye";
Internally + operator uses StringBuffer for concatenating strings.
String b= new StringBuilder(a).append("bye").toString(); (The toString() method of StringBuilder is returning a new String which will be definitely in the Heap since it is created with new String(...). So "bye" will be SECOND STRING IN POOL.)
Now,
b="hellobye" ("hellobye" will be THIRD STRING IN POOL)
First string "hello" is created and added to the string pool.
Next, the String "Bye" is created and added to the string pool.
The concatenation of a and "Bye" results in a new String "helloBye",
which is also added to the string pool.
A total of 3 Strings will be created in the pool: "hello", "Bye",
and "helloBye".
When you create a new StringBuilder and append a string to it, the resulting string will not be added to the string pool. Instead, a new String object will be created in the heap memory to represent the combined string.
So, the code new StringBuilder(a).append("bye") will create one new String object in the heap memory to represent the combined string and one string in pool for "a".
The only part of your question that can be answered with complete certainty is this:
Does append method create the appending strings in the string pool?
The answer is No. The result of a string concatenation that is not a constant expression is not placed in the string pool. At least not in any implementation of mainstream Java to date. However, there is no specification that actually guarantees this.
There are a couple of reasons why we don't know for sure how many strings are "formed".
We don't know when the String objects corresponding to the literals are actually created. In some Java implementation they will be created (and interned) when the code is loaded. In others, the string creation could occur the first time this code is run.
We don't know whether one or both of those literals are used by another class ... and hence whether this code is "forming" them.
Depending on the Java implementation, interning a string (to put it in the string pool) may result in a new String object being created. So you might get a scenario where two String objects get "formed" for each literal.
In short there is enough ambiguity that we cannot be 100% sure of the precise number of strings that are created during the execution of that code.
Does it matter that we don't know for sure?
Frankly, no. It should make zero difference to the way that you write your code1. Let the Java compiler and runtime take care of it ... and use a recent version of Java to get the benefit of the work they have done on optimizing this.
1 - But it is still wise to avoid string concatenation loops. I don't know if they can be optimized.
In your commented version you wrote:
String a = "hello"; // hello is created in string pool
String b = a + "bye"; // new StringBuilder(a).append("bye")
Both of those comments are questionable:
The "hello is created in string pool" comment is questionable for reasons that I gave above.
The new StringBuilder(a).append("bye") pseudo-code is questionable because that is an implementation detail. In Java 9 and later, expressions that involve string concatenations are translated to a invokedynamic bytecode. The JIT compiler generates native instructions directly. See How much does Java optimize string concatenation with +? for more information.

How to get the string from its String.hashCode() value? [duplicate]

This question already has answers here:
how can I get the String from hashCode
(4 answers)
Closed 3 years ago.
I need to somehow get the text from its hash in java.
I have this code:
String myString = new String("creashaks organzine");
int hashCode = myString.hashCode();
System.out.println("Hash:" + hashCode);
The result of this code will be 0.
But the hash of "pollinating sandboxes" string will also be 0.
There might be collisions, for example with "creashaks organzine" and "pollinating sandboxes" and I want to find collisions like in this case.
Since i don't have enough reputation to add comment, i will quote solution from another question
You know that several objects can have same hash(), as it mentioned in java doc for Object.hashCode()
It is not required that if two objects are unequal
* according to the {#link java.lang.Object#equals(java.lang.Object)}
* method, then calling the {#code hashCode} method on each of the
* two objects must produce distinct integer results.
It's obvious you can't restore different objects from same hash code, so it's impossible at all, simple logic.
how can I get the String from hashCode
This is a very interesting thing. Regarding the specification in https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#hashCode() says that the hashCode is calculated from the string content but the example seems to shows that is not true for the first string:
class Main
{
public static void main(String[] args)
{
String myString1 = "creashaks organzine";
String myString2 = "crsomething else";
String myString3 = "crsomething else";
System.out.println("Hash1:" + myString1.hashCode());
System.out.println("Hash2:" + myString2.hashCode());
System.out.println("Hash3:" + myString3.hashCode());
}
}
Outputs:
Hash1:0
Hash2:444616526
Hash3:444616526
But when I modify the string, then I get a different output:
String myString1 = "creashaks organzine...";
System.out.println("Hash1:" + myString1.hashCode());
Outputs:
Hash1:45678
So it seems that somebody tricked us by giving a very rare example string that produced exactly the "0" as output. Here you see that the hashCode is not very unique, so you cannot use is safely to compare strings.
Coming back to your initial question: The hashCode is a number with reduced details, so you cannot calculate it back to the original string. This applies to all hash codes.
Hash codes are so often used in server side databases instead of real password strings. They can be compared but not reconstructed.

What's this Java idiom? String constructor with concatenation

In a code base I'm working with I'm seeing this idiom being used.Can someone explain it for me?
new String("" + number) // `i` is an instance of Integer
For some context, this is approximately what the method looks like:
public String someMethod(String numberString) {
Integer number = new Integer(numberString);
// other stuff happens...
return new String("" + number);
}
It's most likely nothing but an inexperienced Java programmers attempt at converting a number to a String.
Whether converting numbers to Strings using "" + number is good practice is debateable. I for one find String.valueOf(number) to be more clear (although it's semantically equivalent).
It's completely unnecessary to wrap the result in new String(...) unless you (for some unimaginable reason) really need a new string, i.e. one that's referentially distinct from other strings.
This ideom is the easiest way of converting any primitive or Object type to a string.
It is quite easy: Typing "" + number is less work than typing String.valueOf(number) (or Integer.toString(number). The latter is the usual way of transforming an int into a String. Which one is clearer and to be preferred is a matter of taste. You will find advocates for both versions.
But note three things:
Calling String.valueOf(number) is faster, because "" + number will become a string concatenation, it will be compiled to
new StringBuilder().append("").append(number).toString()
However, unless this statement is in a hot place in your code, the difference will not matter at all. Even in a hot place, the difference might still be negligible
Simply calling number.toString() is also an option since number is a boxed integer. However, if number is null, this will trigger a null pointer exception so be careful!
The last line of your example, i.e., new String("" + number); is simply crap! It wraps the result into a newly built string. This creates an unnecessary copy and costs precious extra keystrokes. It also generates unnecessary boilerplate noise in your code. This last line compiles to:
new String(new StringBuilder().append("").append(number).toString())
That is quite some work for transforming int to String. You first create a StringBuilder, then a built String and then a copy of this built String. This creates three objects instead of one.
This idiom is used to automatically convert the integer number to a string.
The String constructor expects an argument of type String. The expression new String(number) would not compile. Concatenting an empty string is a little trick to turn the Integer into a String.
You could of course use new String(number.toString()) or String.valueOf(number) instead.
Note: As Jon Skeet mentions in the comments there is no need to use new Sring() at all. You could just return number.toString(); or return String.valueOf(number)

String objects and reference in java [duplicate]

This question already has answers here:
How many string objects will be created in memory? [duplicate]
(4 answers)
Closed 9 years ago.
String str = "Hello"+"World";
String str1 = str + "hello";
How many objects are created and how many references are created?
String is an immutable object. Whenever you manipulate a String, the JVM creates (at least) a new String and assigns it the new (concatenated) value.
As you did not specify you only care about String objects and references, we need to talk about StringBuffers. StringBuffers are (beside StringBuilders) a class that tries to work around the immutable nature of Strings. We all know, many times we just need to add two or more Strings together.
Imagine this code:
String sentence = "the " + "quick " + "brown " + "fox ";
Often times, when that happens, the Java Compiler will not create these Strings, one at a time adding them together, then forgetting about all intermediary Strings. What happens is that a StringBuffer is created. Then, all single Strings are added by using StringBuffer.append(String), then at the end one String is returned.
What you can say for sure is that 3 String references are created, referencing the inlined (and pooled) Strings "Hello", "World" and "hello". Each reference references a different String. That would have changed if the third word would have been "Hello" as well (uppercase h).

Obfuscation: hide hardcoded values in java [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
hiding strings in Obfuscated code
I'm trying to hide a little some static Strings of my app in order to make it harder to decompile, this way like the constants like cipher algorithms names are harder to find in the obfuscated code.
I've considered things like:
String CONCAT= "concat"+"string";
String RAW_STRING= "raw_string";
String FROM_BYTES=new String("from_bytes".getBytes());
String FROM_CHARS=new String(new char[]{'f','r','o','m','_','c','h','a','r','s'});
String FROM_CHAR2=new String(new char[]{102,114,111,109,95,99,104,97,114,115,95,50});
And the last two options seems to be "darker" than the raw option but I imagine there are better ways for doing this.
How can I improve this? Thanks
For one, you shouldn't just write
String FROM_CHAR2=new String(new char[]{102,114,111,109,95,99,104,97,114,115,95,50});
It's a dead give-away that the char array is actually a String.
You can do a combination of the followings:
put your "String" in an int[] array
or even better, break your String into several int arrays
calculate/manipulate the array's values at various stage of the application, so its value will only become valid at a certain interval during a runtime, guaranteeing that it won't be deciphered at a curious glance by decompiling your code
passes the array(s) back and forth, through local variables, back to instance variables, etc, before finally converting the arrays to a single array to be passed to the String constructor
immediately set the String to null after use, just to reduce the amount of time the actual String exist at runtime
I would prefer to set the value in the static (class) initializer using an decryption algo
Something like
class ...
String CONCAT;
static {
CONCAT = uncrypt ("ahgsdhagcf");
}
where uncrypt might be really a good unencryption algo or somewhat weaker a base64 decode.
In any case you need a simple program to encode your string first.

Categories

Resources