String pool and String[] [duplicate] - java

This question already has answers here:
Questions about Java's String pool [duplicate]
(7 answers)
How do I compare strings in Java?
(23 answers)
how equals method works in java
(1 answer)
String pool vs Constant pool
(3 answers)
Strange String pool behavior
(4 answers)
Closed 5 years ago.
public static void main(String[] args) {
String[] arr = new String[5];
for (int i = 0; i < arr.length; i++) {
arr[i] = "aaa" + i;
}
System.out.println(arr[0] == "aaa0"); // false
String s = "aaa0";
System.out.println(s == arr[0]); // false
}
I have a few question regarding the topic could help me to understand
What are logins behind the fact that String from string arrays don't automatically go to Sting pool, unlike string literals?
Do I correctly understand that only string literals go to the String pool implicitly ?
Do I correctly understand that string array from public static void main ( public static void main(String[] args) ) is not go to the String pool too ?

The compiler transforms that for loop under the covers!
And the resulting bytecode will use a new StringBuilder for each loop iteration... Resulting in "newly" created string objects!
Meaning; in "reality; your loop looks "more" like:
for (int i = 0; i < arr.length; i++) {
StringBuilder builder = new StringBuilder("aaa");
builder.append(i);
arr[i] = builder.toString();
}
(see here on the theoretical background)
That is one of the reasons that using == to compare strings has such a bad reputation... As it tends to lead to unexpected results.
And regarding your comment: the point is not the array you are using (where: you should not be writing into the array passed to main - you can, but it is bad practice).

You can call the intern() method to enforce String pooling, i.e. to store only one copy of each distinct string value.
Check this out:
public static void main(String[] args) {
String[] arr = new String[5];
for (int i = 0; i < arr.length; i++) {
arr[i] = ("aaa" + i).intern();
}
System.out.println(arr[0] == "aaa0");
String s = "aaa0";
System.out.println(s == arr[0]);
}

Use equals() if you want to compare THE CONTENT of two objects. Here are more of an explication
The “==” operator
In Java, when the “==” operator is used to compare 2 objects, it
checks to see if the objects refer to the same place in memory. In
other words, it checks to see if the 2 object names are basically
references to the same memory location.
The equals() method
The equals method is defined in the Object class, from which every
class is either a direct or indirect descendant. By default, the
equals() method actually behaves the same as the “==” operator –
meaning it checks to see if both objects reference the same place in
memory. But, the equals method is actually meant to compare the
contents of 2 objects, and not their location in memory.
System.out.println(arr[0].equals("aaa0")); // It give you True
System.out.println(s == arr[0]); // It give you false

Related

Why does variables of class Test for two different objects gives true for == operation and same operation results in false for String Objects? [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 5 years ago.
For == operation on variables of String for two different objects s and p created using new gives result as false (line 1) which I understand but why does line 3 and 4 ( line number commented ) gives true as Output?
I am aware of the fact that == is meant for reference comparison and that's where i have the doubt if it's meant for reference comparison then why line 4 gives true as j is an integer and there is no immutability concept as for String ( String s ) and everytime a new object has to be created ?
class World
{
public static void main(String[] args)
{
String s=new String("B");
String p=new String("B");
System.out.println(s==p); //false line 1
Test t1= new Test("A",4);
Test t2= new Test("A",4);
System.out.println(t1==t2); //false line 2
System.out.println(t1.s==t2.s); //true line 3
System.out.println(t1.j==t2.j); //true line 4
}
}
class Test
{
String s;
int j;
Test(String s, int j)
{
this.s=s;
this.j=j;
}
}
strings are normally cached in java, so two strings with the same value might have the same reference. (The same goes for Integers, there objects in a certain range are referenced as the same object, if they have the same value). This could lead to having the same object "A" as your value of s for t1 and t2 in the constructors. Two int primitives are always the same if they have the same value.
In Java using the == operator on two integers compares them by value. Meanwhile using == on two strings or your two classes compares their location in memory, not their value.
You need to be careful in the Test class because you’re naming your class fields the same thing as your arguments so you might not actually be assigning values of j and s to what you think you are.
Try changing your constructor to
Test(String str, int i){
s = str;
j = i;
}

Passing by reference in Java. Help me understand [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Immutability of Strings in Java
(26 answers)
Closed 5 years ago.
I have the following code
public static void main(String[] args) {
String word = "Super";
reverseString(word);
System.out.println(word);
}
public static String reverseString(String word) {
String helper = "";
int i = word.length() - 1;
while (i >= 0) {
helper += word.charAt(i);
i--;
}
return helper;
I do not understand why when I'm printing the "word" variable it still prints "Super" even though I changed it in the reverseString method. I understand that strings are passed by reference and not a copy like primitive values.
If I do word = reverseString(word) it prints the reverse what I expect, "repuS"
Thanks
You're not changing the string in reverseString, you're creating a new one and returning the new one (which you've called helper).
A second thing to note about strings in Java is that they're immutable - all string methods return a new string rather than modifying the one you're calling the method on.

String reuse in Java [duplicate]

This question already has answers here:
What is Java String interning?
(8 answers)
Closed 6 years ago.
How does Java decide when a new String should be created?
I assume it depends on the specific JVM implementation/ compiler, but I thought the results of this test were interesting enough to ask the question:
class A { public String test = "test";}
class B { public String test = "test";}
...
public static void main (String[] args)
{
String test = "test";
System.out.println(test == "test"); // true
System.out.println(test == new String("test")); // false
System.out.println(new A().test == new B().test); // true
}
String literals are always interned, this is not directly platform-dependent.
Except when using the explicit initialization idiom through the constructor (new String(someString)).
In that case, a new Object is created, which causes the reference equality operator (==) to return false in your example.
Needless to say, always use equals for reliable String value comparison, but I suspect this falls out of your question's scope.

How to show !equals in if statement (Java)? [duplicate]

This question already has answers here:
How can I express that two values are not equal to eachother?
(4 answers)
Closed 8 years ago.
How is it possible to show if it's not equal (!=, something like this maybe) in an if statement?
For example:
for (int g = 0; g < doglist.size(); g++){
if(doglist.get(g).equals(name)){
System.out.println("There is no dog with that name: ");
}
}
So in this code I want to print the message if the entry in the list is not equal to name. So instead of equals(name) I'll have to use something different. How is this possible?
You can use the NOT operator ! with appropriate parentheses for clarity (though not strictly required).
if (!(condition))
so in your case....
if(!(doglist.get(g).equals(name)))
You should write
if (!doglist.get(g).equals(name))
About your idea of using !=: For primitive data types, yes, it's correct to test equality using !=. .equals() is for object data types. However, applying != to an object would be testing whether the memory location of the operands is the same, which is not the relevant information. .equals() is what tests for whether the objects are actually equal.
For example, when comparing ints (a primitive type), you would use !=:
int a = 0, b = 1;
if (a != b) doSomething(); //Calls the method
Primitive types do not recognize the .equals() method at all. But if you want to compare Strings (an object type), you would use !<object>.equals():
String s1 = "Hello", s2 = "World";
if (!s1.equals(s2)) doSomething(); //Calls the method
If you used != with an object, it would compile, but likely would not produce the desired output:
String s1 = "Hello!";
String s2 = "Hello!"; //Make a new object with the same data -- contains "Hello!"
if (s1 != s2) doSomething(); //Will run doSomething(), even though s1.equals(s2)

String comparison in java does not gives the desired results [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
I tried with the following class :
public class EqualMethodTestWithNew {
public static void main(String[] args) {
String value = "xxx";
String name = new String("xxx") ;
System.out.println("hascode : value : "+value.hashCode());
System.out.println("hascode : name : "+name.hashCode());
if (value == name) {
System.out.println("equal == 1");
} else {
System.out.println("false == 1");
}
}
}
though the hasCode is same for the both variable it prints the false == 1. could some one explain the reason why?
thanks
You need to understand what exactly is happening when you execute the 2 string statements.
String value = "xxx";
The above line creates a new compile time constant string which does into the String intern pool.
String name = new String("xxx") ;
But in this case, since you're using the new operator, it creates a new String object which goes in the object heap. It does not have the same address as the one which was created in the previous statement.
The hashCode() method is based on the contents of the String which are the same, but that doesn't mean that they both refer to the same String object in the memory.
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] // would return same value for all String objects having the same content
To compare the values, you need to use equals() method.
And if you want to compare the object references use the == operator. In your case, since both refer to difference objects, you get the output as false.
Alternatively, you can ask the compiler to check and fetch the reference of a String with the same value already existing in the String pool by using the intern() method.
String value = "xxx";
String name = new String("xxx");
name = name.intern(); // getting reference from string pool
Now you'll get the output as equal == 1 when your do if (value == name) {.
You should be using equals method instead of == opertaor.
if (value.equals(name)) {
System.out.println("equal == 1");
} else {
System.out.println("false == 1");
}
Note that:
== tests for reference equality.
.equals() tests for value equality.
Please see here for more information.
The reason why your code is not working is that == tests whether the reference to the object is the same, and that is not your case. To compare the value of the string, you need to use the .equals(String str) method.
if (value.equals(name)) {
...
}
String should be compared with equals() method, not ==. You are trying the check the equality of the memory address of both instances (actually they are not) instead of the value in the String instances. So, use
if(value.equals(name)) {
System.out.println("equal == 1");
}
Strings are compared using equal() method. == compares the two objects are equal are not.

Categories