Difference between substring and string in java [duplicate] - java

This question already has answers here:
Java: Why can String equality be proven with ==?
(3 answers)
Closed 8 years ago.
class test {
public static void main(String[] args) {
String a = "Hiabc";
String b = "abc";
String c = "abc";
System.out.println(a.substring(2,5)==b);
System.out.println(b==c);
}
}
output:
false
true
As far as I understand, Java's == look for addresses of the two compared objects. Yet, I don't understand why b==c is true because they must have different addresses. Also, if b==c, then why is a.substring(2,5), which is "abc" == b false?

As far as I understand, Java's == look for addresses of the two compared objects.
Almost correct. Java uses references not addresses, e.g. a reference is strongly typed: See https://softwareengineering.stackexchange.com/questions/141834/how-is-a-java-reference-different-from-a-c-pointer
why b==c is true
The variable b and c are initialized with the same string reference, because they reference the same string literal "abc".
why doesn't substring expression reference the string literal "abc"?
Because the javadoc of substring() says
Returns a new string that is a substring of this string.
So the method does not ensure that a reference to a string from the constant pool is returned. If you want this you have to do
a.substring(2,5).intern()
and than
a.substring(2,5).intern()==b
will be true.

Never compare strings with == in Java.
Use .equal or .equalIgnoreCase methods instead.
The difference between a.substring(2,5) and b is because substring created another String object and it's on a different location than b. It's not about the characters ...

Related

Memory reference [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 2 years ago.
Is c point to a or is c point to the same memory that a is pointing to?
Why does the following code print "We are equal"?
Thanks in advance
public static void main(String args[]) {
String a = "10";
String b = "10";
String c = a;
if(c.equals(b)) {
System.out.println("We are equal ");
}
else {
System.out.println("Not equal! ");
}
}
Java stores objects by reference... the reference just happens to be the value when we use primitives.
int is a primitive so
a == c => true
a == b => true
b == c => true
With Strings the situation is slightly different. Strings are effectively char arrays: char[] but are not considered primitive types in Java.. so:
"str1" == "str1" => false since you're comparing two object references now.
For this reason the Object class has the equals() method which allows you to compare reference objects (non-primitives) via something other than the object reference ID. The String (a subclass of Object.class) class overrides the equals method.
In your example (above) you say:
So why is ab==abc false. They are both pointing to same address.
This is incorrect. ab points to String that is "meowdeal" and abc points to a String that is also "meowdeal"... but crucially they are two distinct instances. Therefore:
ab==abc => false - here your checking for reference equality - are they the same object reference (no they are not)
ab.equals(abc) => true - here you're checking for string equality (is ab's "meowdeal" the same as abc's "meowdeal" - yes it is.
This is one of those curveball interview questions you might get from time to time so worth being aware of.

String comparison and interning

The following code (from an interview) produces an output of false, but I believe it should be true.
public static void main(String[] args) {
String a = "hello";
String b = a + "world";
String c = "helloworld";
System.out.println(b==c);
}
I thought that constant String expressions were interned, and a + "world" is a constant, so it should intern "hello world".
Can someone explain why the output is false?
Java interns all Strings that are compile time constants. However, only Strings declared by concatenating String literals are considered a compile time constant and so be interned.
This is because the compiler looks only at the line being compiled, so it has no idea if a if a is a constant or not. For example, a could be declared as:
String a = new Date().toString();
Hence, c is a different instance of String than b.
When you do this,
String b=a+"world";
The compiler chooses a StringBuilder based concatenation of String objects like so,
StringBuilder sb = new StringBuilder(a);
sb.append("world");
String b = sb.toString();
This yields a different reference, hence returning false as in your case.
But if you use this,
String b="hello"+"world";
Then the compiler identifies it as a constant, and both the b and c variables reference the same literal in the constant pool. Hence it returns true.
When you assign strings like in your example, a, b, and c are separate String objects. So when you compare them you get false because they are not the same object. == in Java does not do a character-by-character comparison of the string. That's what String.equals() is for.
This is a solid summary to read to understand: How do I compare strings in Java?
The code you are looking at does an equality comparison between two variables that point to two different string instances, which are diferent objects stored in different places in memory (among other things) and are therefore different even though the string they represent is the same.
To do a string comparison you would need to use
stringInstance.equals(anotherStringInstance)
If you did something like this
String a = "abcde";
String b = a;
Then you would get a == b to be true as both variables point to the same object.

Java String pool Storage error [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 6 years ago.
public class HelloWorld{
public static void main(String []args){
String a= "hello";
String ab= a +"John";
String abc = "helloJohn";
System.out.println(ab==abc);
}
}
It prints ab==abc false. Shouldnt it be true..??
Use yourStringVar.equals(anotherString) to check if they contain the same sequence of character, use == to check if they refer to the same object.
In java, String is an object, so two String-objects which have same content will not be equal (because those are different objects), hence abc == ab is not true.
But there are methods to compare the contents of String objects. These are:
abc.equals(ab)
or
abc.compareTo(ab) == 0
You should use for String equals/equalsIgnoreCase. '==' compares objects, NOT VALUES. Because when you make String a = "aa" means you create new object.(like new String("aa")). In java there're equals() and hashCode() methods inherited from Object class, but you may override them.

Comparing Same Object of String with '==' and getting different result in both scenerio, where the String Object Value is same [duplicate]

This question already has answers here:
String.equals versus == [duplicate]
(20 answers)
How do I compare strings in Java?
(23 answers)
Closed 7 years ago.
In Program 1 I have declared two String and initialized them as "MADAM". When running I am checking the equality of their reference variable (by '==' operator') then I am getting a "true" response.
But in Program 2 I am declaring a String 'S' and initialize it as "MADAM". After that i am running a reverse loop and storing the characters of 'S' in reverse order in other String variable. Now i have again tried to check the equality of reference variable (by '==' operator') and am getting the response as 'false'. As both the String objects are of same value and are stored in constant Pool Area so both the variable should equate and the output in both the scenario should be 'true'. But WHY it is not same?
Program 1:
class Reverse {
public static void main(String[] args) {
String s="MADAM"; String rev="MADAM"; System.out.println(s==rev);
}
}
Output - true
Program 2:
class Reverse {
public static void main(String[] args) {
String s="MADAM"; String rev="";
for(int x=s.length()-1;x>=0;x--) { rev+=s.charAt(x); }
System.out.println(s==rev);
}
}
Output- false
In program 1 java compiler saves "MADAM" string in one memory location and assigns both "s" and "rev" to that location hence "s==rev" returns true because they both refer to the same address.
you should use "equals()" method to compare two strings. e.equals(rev);
have a look at this question:
Java String.equals versus ==
In your first class both strings are initialize to same object. So both are pointing to same memory location.
Next class, Rev is intilialized to "" value and see to madam so both have got different memory location. So false.
In essence,
if you use == for comparison, you are comparing their identity.
If you want to compare the object's value, use .equals()
String s="MADAM"; String rev="MADAM"; System.out.println(s==rev);
The above code will return true, because both Strings will be stored in the same memory location.
However, you can try the following, it will return you false:
String s1 = "aaa";
String s2 = new String("aaa");
System.out.println(s1 == s2); //false (comparing memory location)
System.out.println(s1.equals(s2)); //true (comparing value)
Side note: It is generally a bad practice to create Strings using new String(""). It was only used for demonstration purposes only.

Strange Behaviour of Strings when using with java.util.Scanner [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
Actually am testing the functionality of Scanner.
I have a very simple program which has a String variable which contains "abc".Then am reading other String(value "abc") from Scanner using next() method(even i tried with nextLine()).
Then am comparing using the ==, to check whether they are equal according to ==(i know i can compare with equals method which is working as excepted), the strange thing is that it is returning false when i compare using == , even though their hashcode() s are equal and equals() method returning true..
import java.util.Scanner;
public class Tester1234 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
String str1="abc";
System.out.println("Eneter abc");
String str2=scanner.next();
System.out.println("str1.hascode()"+str1.hashCode()+"\tstr2.hascode()"+str2.hashCode()+"\tstr2.equals(str1)"+str1.equals(str2));
if(str1==str2)
{
System.out.println("equal");
}
else
{
System.out.println("not equal");
}
}
}
I want to know why it is behaving like this ??
Thanks...!
You are wrong as for the statement that
i know Strings with same content will point to same object in StringPool...
It is true as for literals whitch are hardcoded strings in the code. Compiler creates string pool on compile time and use existing references. But if you are building string on runtime using StringBuilder/StringBuffer (what i belive the Scanner does internally) you are NOT USING entities in string pool, thats why you will get two different objects (references) for the same string content. Workaround for such behaviour is to use intern() however it is performance hit, as interned strings are goint into permgen, and will not be garbage collected.
If we create an String like this...
String str1 = "abc";
object str1 created in String-Pool, and if we create
String str2 = new String("abc");
then, it created in heap, means another new Object.
this is the reason that your condition if(str1==str2) returns false, because these both are different objects.
But there hashcode is equal because both are "abc", so equals method returns true.
you are right that hashcode and equals returning true, hence it will return true for str2.equals(str1).
But str2 is new String and hence it is having difference memory address thats why it will not work for str2==str1. here you are comparing memory address and not content of the string.

Categories

Resources