What is String pool in Java? [duplicate] - java

This question already has answers here:
What is the Java string pool and how is "s" different from new String("s")? [duplicate]
(5 answers)
Closed 9 years ago.
I am confused about StringPool in Java. I came across this while reading the String chapter in Java. Please help me understand, in layman terms, what StringPool actually does.

This prints true (even though we don't use equals method: correct way to compare strings)
String s = "a" + "bc";
String t = "ab" + "c";
System.out.println(s == t);
When compiler optimizes your string literals, it sees that both s and t have same value and thus you need only one string object. It's safe because String is immutable in Java.
As result, both s and t point to the same object and some little memory saved.
Name 'string pool' comes from the idea that all already defined string are stored in some 'pool' and before creating new String object compiler checks if such string is already defined.

I don't think it actually does much, it looks like it's just a cache for string literals. If you have multiple Strings who's values are the same, they'll all point to the same string literal in the string pool.
String s1 = "Arul"; //case 1
String s2 = "Arul"; //case 2
In case 1, literal s1 is created newly and kept in the pool. But in case 2, literal s2 refer the s1, it will not create new one instead.
if(s1 == s2) System.out.println("equal"); //Prints equal.
String n1 = new String("Arul");
String n2 = new String("Arul");
if(n1 == n2) System.out.println("equal"); //No output.
http://p2p.wrox.com/java-espanol/29312-string-pooling.html

Let's start with a quote from the virtual machine spec:
Loading of a class or interface that contains a String literal may create a new String object (ยง2.4.8) to represent that literal. This may not occur if the a String object has already been created to represent a previous occurrence of that literal, or if the String.intern method has been invoked on a String object representing the same string as the literal.
This may not occur - This is a hint, that there's something special about String objects. Usually, invoking a constructor will always create a new instance of the class. This is not the case with Strings, especially when String objects are 'created' with literals. Those Strings are stored in a global store (pool) - or at least the references are kept in a pool, and whenever a new instance of an already known Strings is needed, the vm returns a reference to the object from the pool. In pseudo code, it may go like that:
1: a := "one"
--> if(pool[hash("one")] == null) // true
pool[hash("one") --> "one"]
return pool[hash("one")]
2: b := "one"
--> if(pool[hash("one")] == null) // false, "one" already in pool
pool[hash("one") --> "one"]
return pool[hash("one")]
So in this case, variables a and b hold references to the same object. IN this case, we have (a == b) && (a.equals(b)) == true.
This is not the case if we use the constructor:
1: a := "one"
2: b := new String("one")
Again, "one" is created on the pool but then we create a new instance from the same literal, and in this case, it leads to (a == b) && (a.equals(b)) == false
So why do we have a String pool? Strings and especially String literals are widely used in typical Java code. And they are immutable. And being immutable allowed to cache String to save memory and increase performance (less effort for creation, less garbage to be collected).
As programmers we don't have to care much about the String pool, as long as we keep in mind:
(a == b) && (a.equals(b)) may be true or false (always use equals to compare Strings)
Don't use reflection to change the backing char[] of a String (as you don't know who is actualling using that String)

When the JVM loads classes, or otherwise sees a literal string, or some code interns a string, it adds the string to a mostly-hidden lookup table that has one copy of each such string. If another copy is added, the runtime arranges it so that all the literals refer to the same string object. This is called "interning". If you say something like
String s = "test";
return (s == "test");
it'll return true, because the first and second "test" are actually the same object. Comparing interned strings this way can be much, much faster than String.equals, as there's a single reference comparison rather than a bunch of char comparisons.
You can add a string to the pool by calling String.intern(), which will give you back the pooled version of the string (which could be the same string you're interning, but you'd be crazy to rely on that -- you often can't be sure exactly what code has been loaded and run up til now and interned the same string). The pooled version (the string returned from intern) will be equal to any identical literal. For example:
String s1 = "test";
String s2 = new String("test"); // "new String" guarantees a different object
System.out.println(s1 == s2); // should print "false"
s2 = s2.intern();
System.out.println(s1 == s2); // should print "true"

Related

Why the string 'java' cann't be added to 'String Pool'

The following code confuses me, could anyone explain why the two tests behave differently? Why does the String comparison in the first test return false while the comparison in the second test returns true?
public class Student {
/**
* Why the string "java" doesn't added to the 'String Pool' by intern() method ?
*/
#Test
public void test1() {
String str1 = new String("ja") + new String("va");
str1.intern();
String str2 = "java";
// Result:false
System.out.println("Result:" + (str1 == str2));
}
/**
* Any other strings will be added to 'String Pool' as expected after intern() is invoked.
*/
#Test
public void test2() {
String str1 = new String("ja1") + new String("va");
str1.intern();
String str2 = "ja1va";
// Result:true
System.out.println("Result:" + (str1 == str2));
}
You're basically checking whether a string was already in the string pool. The string "java" isn't added to the pool by calling intern in your first piece of code because it's already in the string pool. In each method, your code:
Creates a new string
Calls intern on the newly created string (but ignores the result; almost always a bad idea, and you can detect the existence of a previous value in the string pool easily by using the return value)
Compares the new string with a string literal, which will always use the result that's now in the string pool
Now the call to intern will add the target string to the pool if it doesn't already exist, so your comparison will return true if and only if the new string value was not previously in the string pool. This is equivalent to testing whether intern returns a different reference to the target of the call.
For any given string reference, there are three possibilities:
That exact reference is present in the string pool already. (That can't be the case in your code, because you're creating a new string.)
A reference to an equal string is present in the string pool. In that case, intern() will return the existing reference.
No equal string is present in the string pool. In that case, the target of the call will be added to the string pool, and the same reference returned.
What you're seeing is the result of other code putting things in the string pool - quite possibly as part of loading classes. Here's an example to demonstrate that:
public class Test {
public static void main(String... args) {
checkInterned("ja", "va");
checkInterned("ja", "va.lang");
checkInterned("ja", "va.other");
checkInterned("Int", "eger");
checkInterned("abc", "def");
checkInterned("Te", "st");
checkInterned("Te", "st2");
checkInterned("check", "Interned");
checkInterned("check", "Interned2");
}
public static void checkInterned(String start, String end) {
String x = start + end;
String y = x.intern();
System.out.println(x + " was interned already? " + (x != y));
}
}
Output:
java was interned already? true
java.lang was interned already? true
java.other was interned already? false
Integer was interned already? true
abcdef was interned already? false
Test was interned already? true
Test2 was interned already? false
checkInterned was interned already? true
checkInterned2 was interned already? false
So the interned values are:
java
java.lang
Integer
Test
checkInterned
They're all names that would naturally come up when loading classes (including the one being run).
I suspect that "java" is only a special case here in that there may well be lots of code within the JRE that checks whether a string starts with "java" as a reserved name.
This doesn't indicate anything about "java" being a keyword though - it's just "a string that's already in the string pool". You don't need to treat it any differently.
The first thing to realize is that str1.intern() doesn't change the str1 reference. It returns the interned reference. So if you wanted str1 to now be that reference, you'd have to do:
str1 = str1.intern();
So, why the difference? In a nutshell, because the JVM already has a string "java" in its thread pool, because of various internals.
In the first example, str1 starts off as a newly instantiated String (as I think you understand). You then call str1.intern(), which returns the interned reference of a pre-existing String "java", but you don't do anything with that reference. When you then compare str1 == "java", you're comparing the reference to the newly instantiated object with the reference to the interned object, and get false.
In the second example, "ja1va" does not exist in the string pool to start off. When you call str1.intern(), that method puts "ja1va" into the pool, with its current reference (that is, str1) as the canonical reference. When you subsequently refer to the "ja1va" literal string, the JVM looks to see whether it's already in the pool, sees that it is, and uses it. Thus, you get true.
In other words, in the first case, you're creating a new String object and then not actually grabbing its interned equivalent. In the second case, you're creating a new String object, defining that as the interned reference, and then reloading it via a string literal.

Every time I use String, does it create a new String object?

Let's say that I need to iteratively retrieve a value of the same key from a Java hashmap.
for(int i=0; i<INTEGER.MAX; i++)
map.get("KEY");
In this case, is the "KEY" string created every time I call map.get("KEY")? I was wondering if it's always better to have a String constant, or it doesn't matter.
No. String constants are interned automatically, so any identical string literals all reference the same object in memory.
Some more information on this: http://www.xyzws.com/Javafaq/what-is-string-literal-pool/3
An example of this:
String s1 = "Test";
String s2 = "Test";
String s3 = new String("Test");
s1 == s2;//Evaluates to true, because they are the same object (both created with string literals)
s1 == s3;//Evaluates to false, because they are different objects containing identical data
Yes/No Answer depends on how you create String Objects. Below are the four scenarios I can think of as of now.
Yes Cases
new String() always creates new Object. It is not internedn(Doesn't go to String pool) so you
can not take it back from memory.
Concatenation ( "a" + "b" ) always creates new String Object and it is not interned (Doesn't go to String pool).
No Cases
String a ="aa"; if already available it retrieves from the pool, when not available it creates a new object which is interned also (Goes to String pool as well)
new String().intern() or "aa".intern(); if already available it retrieves from pool , when not available it creates new object which
is interned also (Goes to String pool as well).
is the "KEY" string created every time I call map.get("KEY")?
No.
Java Strings are immutable, which allows the Java compiler to use a single instance for all string literals.
That is: all identical string literals in your program will reference a single string object.
In the rare cases you need identical strings to be wrapped in two separate objects, you must explicitly
instantiate a String object:
String s1 = "bla";
String s2 = "bla";
// s1 == s2
String s3 = new String ("bla");
// s1 != s3

What is the purpose of Java's String.intern()?

I know there are two ways of creating String in Java:
String a = "aaa";
String b = new String("bbb");
With the first way Java will definitely create a String object in the string pool and make a refer to it. (Assume "aaa" wan't in the pool before.)
With the second method, an object will be created in the heap, but will jvm also create an object in the string pool?
In this post Questions about Java's String pool, #Jesper said:
If you do this:
String s = new String("abc");
then there will be one String object in the pool, the one that represents the literal "abc", > and there will be a separate String object, not in the pool, that contains a copy of the > content of the pooled object.
If that's true, then every time with the new String("bbb");, a object "bbb" is created in the pool, which means by either way above, java will always create a string object in the pool. Then what is intern() used for ? In the docs http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#intern(), it says:
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
That means there are cases that a string is not in the pool, is that possible ? Which one is true ?
As you know that String is an immutable object in Java programming language, which means once constructed can not be altered. Due to this, JVM has the ability to maintain a literal pool which is helpful to reduce the memory usage and to increase the performance. Each time when a String literal is used JVM checks the literal pool. If the literal is already available, the same reference would be returned. If the literal is not available, a new String object will be created and added in the literal pool.
This theory is applied when you try to create a String like a primitive or a literal/constant.
String str = "bbb";
But when you create a new String object
String str = new String("bbb");
the above mentioned rules are overridden and a new instance is created always.
But the intern API in the String class can be used to pick the String reference from the literal pool even though you create a String using new operator. Please check the below given example. Although the str3 is created using new operator since we used the intern method JVM picked up the reference from the literal pool.
public class StringInternExample {
public static void main(final String args[]) {
final String str = "bbb";
final String str1 = "bbb";
final String str2 = new String("bbb");
final String str3 = new String("bbb").intern();
System.out.println("str == str1 : "+(str == str1));
System.out.println("str == str2 : "+(str == str2));
System.out.println("str == str3 : "+(str == str3));
}
}
Output of above code:
str == str1 : true
str == str2 : false
str == str3 : true
You can have a look: Confusion on string immutability
Source of answer: http://ourownjava.com/java/java-string-immutability-and-intern-method/
Shishir
There are essentially two ways that our String objects can enter in to the pool:
Using a literal in source code like "bbb".
Using intern.
intern is for when you have a String that's not otherwise from the pool. For example:
String bb = "bbb".substring(1); // substring creates a new object
System.out.println(bb == "bb"); // false
System.out.println(bb.intern() == "bb"); // true
Or slightly different:
System.out.println(new String("bbb").intern() == "bbb"); // true
new String("bbb") does create two objects...
String fromLiteral = "bbb"; // in pool
String fromNewString = new String(fromLiteral); // not in pool
...but it's more like a special case. It creates two objects because "bbb" refers to an object:
A string literal is a reference to an instance of class String [...].
Moreover, a string literal always refers to the same instance of class String.
And new String(...) creates a copy of it.
However, there are many ways String objects are created without using a literal, such as:
All the String methods that perform some kind of mutation. (substring, split, replace, etc.)
Reading a String from some kind of input such as a Scanner or Reader.
Concatenation when at least one operand is not a compile-time constant.
intern lets you add them to the pool or retrieve an existing object if there was one. Under most circumstances interning Strings is unnecessary but it can be used as an optimization because:
It lets you compare with ==.
It can save memory because duplicates can be garbage collected.
Yes, new String("abc") will create a new object in memory, and thus it is advised to avoid it. Please have a look at item 5 of Josh Bloch's Effective Java, "Avoid creating unnecessary objects" where it is better explained:
As an extreme example of what not to do, consider this statement:
String s = new String("stringette"); // DON'T DO THIS!
The statement
creates a new String instance each time it is executed, and none of
those object creations is necessary. The argument to the String
constructor ("stringette") is itself a String instance, functionally
identical to all of the objects created by the constructor. If this
usage occurs in a loop or in a frequently invoked method, millions of
String instances can be created needlessly. The improved version is
simply the following:
String s = "stringette";
This version uses a
single String instance, rather than creating a new one each time it is
executed. Furthermore, it is guaranteed that the object will be reused
by any other code running in the same virtual machine that happens to
contain the same string literal [JLS, 3.10.5].
http://uet.vnu.edu.vn/~chauttm/e-books/java/Effective.Java.2nd.Edition.May.2008.3000th.Release.pdf
With the second method, an object will be created in the heap, but will jvm also create an object in the string pool?
Yes, but it is the string literal "bbb" which ensures the interned string1. The string constructor creates a new string object which is a copy with the same length and content - the newly created string is not automatically interned.
If that's true, then every time with the new String("bbb");, a object "bbb" is created in the pool, which means by either way above, java will always create a string object in the pool. Then what is intern() used for ?
Only string literals are automatically interned. Other string objects must be manually interned, if such is the desired behavior.
That means there are cases that a string is not in the pool, is that possible ?
With the exception of manual calls to String.intern, only string literals result in interned strings.
While I would recommend using a specialized collection for such cases, interning may be useful where it can be used to avoid creating extra duplicate objects. Some use-cases where interning can be beneficial - as in, the same string value can appear many times - is in JSON keys and XML element/attribute names.
1 This is trivial to reason, consider:
String _b = "bbb"; // string from string literal (this is interned)
String b = new String(_b); // create a NEW string via "copy constructor"
b == _b // -> false (new did NOT return an interned string)
b.equals(_b) // -> true (but it did return an equivalent string)
b.intern() == _b // -> true (which interns to .. the same string object)

String.intern is it the same just copy an object reference in Java?

Is doing:
String a = new String();
String b = a;
and doing:
String a = new String();
String b = a.intern();
is the same ?
Actually, the reference are all the same if I test:
String a = new String("te");
String b = a.intern();
String c = a;
String d = "t" + "e";
System.out.print(a.equals(b));
System.out.print(b.equals(c));
System.out.print(a.equals(d));
Cause the String will ever be in the String pool ?
Your equals tests aren't checking for references - they're checking for string equality. You should be using == to check the references for identity. Effectively, you're making the common rookie Java mistake in reverse - usually people use == when they should be using equals. In this particular case, all of those will print false, because there are two String objects involved (the string from the constant pool, and the new string created in the first line). If we call these #1 and #2 respectively, we end up with:
a = #2 // Explicit call to string constructor
b = #1 // intern will return reference to constant pool instance
c = #2 // Direct assignment
d = #1 // Equivalent string constant, so reference to constant pool instance
However, you may find this interesting:
String a = "te";
String b = a.intern();
String c = "t" + "e";
System.out.println(a == b); // true
System.out.println(a == c); // true
"te" and "t" + "e" are equal constant string expressions, so end up as references to a single string, and calling intern on a string already in the literal pool won't have any effect.
To start off: "t" + "e" is a String literal, because it will be optimised by the compiler. This string literal is also used in this line:
String a = new String("te");
Now, the String(String) constructor makes a physical copy of the String. So, this means that a and d are not the same object.
Then: String.equals(String) compares two Strings. It says if the content was equal and not the object. This means you might have two different String objects which have the same sequence of characters, which will make the String.equals(String) return true.
String.intern() puts the String in the String pool, if it isn't yet in it. But this method can't change the object itself. So this code example will print false:
String literal = "lit";
String nonLiteral = "abclit".substring(3); // equals "lit"
nonLiteral.intern(); // "lit" was already in the String pool
// but `nonLiteral` is still `nonLiteral`
System.out.println(literal == nonLiteral); // false
However if you would do this: it will return true:
String literal = "lit";
String nonLiteral = "abclit".substring(3); // equals "lit"
nonLiteral = nonLiteral.intern(); // "lit" was already in the String pool and
// it will return the object `literal`.
// Now the value is replaced.
System.out.println(literal == nonLiteral); // true
If that string value has already been interned from a different String instance, intern() will return the earlier instance.
Using equals doesn't test the equality of the references. It tests the equality of the contents of the String. You need to use == to test the equality of the references.
To answer your question, no, it's not the same. The first snippet assigns two references (a and b) to the same String. The second one creates a String, assigns it to a, then interns the String and assigns the String that the intern pool returns to b. a and b could thus refer to two different String instances (and certainly will, because the empty String is in the pool for sure, thus intern() will not return the STring referred to by a, but will returned the pooled empty String)

String.equals versus == [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
This code separates a string into tokens and stores them in an array of strings, and then compares a variable with the first home ... why isn't it working?
public static void main(String...aArguments) throws IOException {
String usuario = "Jorman";
String password = "14988611";
String strDatos = "Jorman 14988611";
StringTokenizer tokens = new StringTokenizer(strDatos, " ");
int nDatos = tokens.countTokens();
String[] datos = new String[nDatos];
int i = 0;
while (tokens.hasMoreTokens()) {
String str = tokens.nextToken();
datos[i] = str;
i++;
}
//System.out.println (usuario);
if ((datos[0] == usuario)) {
System.out.println("WORKING");
}
}
Use the string.equals(Object other) function to compare strings, not the == operator.
The function checks the actual contents of the string, the == operator checks whether the references to the objects are equal. Note that string constants are usually "interned" such that two constants with the same value can actually be compared with ==, but it's better not to rely on that.
if (usuario.equals(datos[0])) {
...
}
NB: the compare is done on 'usuario' because that's guaranteed non-null in your code, although you should still check that you've actually got some tokens in the datos array otherwise you'll get an array-out-of-bounds exception.
Meet Jorman
Jorman is a successful businessman and has 2 houses.
But others don't know that.
Is it the same Jorman?
When you ask neighbours from either Madison or Burke streets, this is the only thing they can say:
Using the residence alone, it's tough to confirm that it's the same Jorman. Since they're 2 different addresses, it's just natural to assume that those are 2 different persons.
That's how the operator == behaves. So it will say that datos[0]==usuario is false, because it only compares the addresses.
An Investigator to the Rescue
What if we sent an investigator? We know that it's the same Jorman, but we need to prove it. Our detective will look closely at all physical aspects. With thorough inquiry, the agent will be able to conclude whether it's the same person or not. Let's see it happen in Java terms.
Here's the source code of String's equals() method:
It compares the Strings character by character, in order to come to a conclusion that they are indeed equal.
That's how the String equals method behaves. So datos[0].equals(usuario) will return true, because it performs a logical comparison.
It's good to notice that in some cases use of "==" operator can lead to the expected result, because the way how java handles strings - string literals are interned (see String.intern()) during compilation - so when you write for example "hello world" in two classes and compare those strings with "==" you could get result: true, which is expected according to specification; when you compare same strings (if they have same value) when the first one is string literal (ie. defined through "i am string literal") and second is constructed during runtime ie. with "new" keyword like new String("i am string literal"), the == (equality) operator returns false, because both of them are different instances of the String class.
Only right way is using .equals() -> datos[0].equals(usuario). == says only if two objects are the same instance of object (ie. have same memory address)
Update: 01.04.2013 I updated this post due comments below which are somehow right. Originally I declared that interning (String.intern) is side effect of JVM optimization. Although it certainly save memory resources (which was what i meant by "optimization") it is mainly feature of language
The == operator checks if the two references point to the same object or not.
.equals() checks for the actual string content (value).
Note that the .equals() method belongs to class Object (super class of all classes). You need to override it as per you class requirement, but for String it is already implemented and it checks whether two strings have the same value or not.
Case1)
String s1 = "Stack Overflow";
String s2 = "Stack Overflow";
s1 == s1; // true
s1.equals(s2); // true
Reason: String literals created without null are stored in the string pool in the permgen area of the heap. So both s1 and s2 point to the same object in the pool.
Case2)
String s1 = new String("Stack Overflow");
String s2 = new String("Stack Overflow");
s1 == s2; // false
s1.equals(s2); // true
Reason: If you create a String object using the `new` keyword a separate space is allocated to it on the heap.
equals() function is a method of Object class which should be overridden by programmer. String class overrides it to check if two strings are equal i.e. in content and not reference.
== operator checks if the references of both the objects are the same.
Consider the programs
String abc = "Awesome" ;
String xyz = abc;
if(abc == xyz)
System.out.println("Refers to same string");
Here the abc and xyz, both refer to same String "Awesome". Hence the expression (abc == xyz) is true.
String abc = "Hello World";
String xyz = "Hello World";
if(abc == xyz)
System.out.println("Refers to same string");
else
System.out.println("Refers to different strings");
if(abc.equals(xyz))
System.out.prinln("Contents of both strings are same");
else
System.out.prinln("Contents of strings are different");
Here abc and xyz are two different strings with the same content "Hello World". Hence here the expression (abc == xyz) is false where as (abc.equals(xyz)) is true.
Hope you understood the difference between == and <Object>.equals()
Thanks.
== tests for reference equality.
.equals() tests for value equality.
Consequently, if you actually want to test whether two strings have the same value you should use .equals() (except in a few situations where you can guarantee that two strings with the same value will be represented by the same object eg: String interning).
== is for testing whether two strings are the same Object.
// These two have the same value
new String("test").equals("test") ==> true
// ... but they are not the same object
new String("test") == "test" ==> false
// ... neither are these
new String("test") == new String("test") ==> false
// ... but these are because literals are interned by
// the compiler and thus refer to the same object
"test" == "test" ==> true
// concatenation of string literals happens at compile time resulting in same objects
"test" == "te" + "st" ==> true
// but .substring() is invoked at runtime, generating distinct objects
"test" == "!test".substring(1) ==> false
It is important to note that == is much cheaper than equals() (a single pointer comparision instead of a loop), thus, in situations where it is applicable (i.e. you can guarantee that you are only dealing with interned strings) it can present an important performance improvement. However, these situations are rare.
Instead of
datos[0] == usuario
use
datos[0].equals(usuario)
== compares the reference of the variable where .equals() compares the values which is what you want.
Let's analyze the following Java, to understand the identity and equality of Strings:
public static void testEquality(){
String str1 = "Hello world.";
String str2 = "Hello world.";
if (str1 == str2)
System.out.print("str1 == str2\n");
else
System.out.print("str1 != str2\n");
if(str1.equals(str2))
System.out.print("str1 equals to str2\n");
else
System.out.print("str1 doesn't equal to str2\n");
String str3 = new String("Hello world.");
String str4 = new String("Hello world.");
if (str3 == str4)
System.out.print("str3 == str4\n");
else
System.out.print("str3 != str4\n");
if(str3.equals(str4))
System.out.print("str3 equals to str4\n");
else
System.out.print("str3 doesn't equal to str4\n");
}
When the first line of code String str1 = "Hello world." executes, a string \Hello world."
is created, and the variable str1 refers to it. Another string "Hello world." will not be created again when the next line of code executes because of optimization. The variable str2 also refers to the existing ""Hello world.".
The operator == checks identity of two objects (whether two variables refer to same object). Since str1 and str2 refer to same string in memory, they are identical to each other. The method equals checks equality of two objects (whether two objects have same content). Of course, the content of str1 and str2 are same.
When code String str3 = new String("Hello world.") executes, a new instance of string with content "Hello world." is created, and it is referred to by the variable str3. And then another instance of string with content "Hello world." is created again, and referred to by
str4. Since str3 and str4 refer to two different instances, they are not identical, but their
content are same.
Therefore, the output contains four lines:
Str1 == str2
Str1 equals str2
Str3! = str4
Str3 equals str4
You should use string equals to compare two strings for equality, not operator == which just compares the references.
It will also work if you call intern() on the string before inserting it into the array.
Interned strings are reference-equal (==) if and only if they are value-equal (equals().)
public static void main (String... aArguments) throws IOException {
String usuario = "Jorman";
String password = "14988611";
String strDatos="Jorman 14988611";
StringTokenizer tokens=new StringTokenizer(strDatos, " ");
int nDatos=tokens.countTokens();
String[] datos=new String[nDatos];
int i=0;
while(tokens.hasMoreTokens()) {
String str=tokens.nextToken();
datos[i]= str.intern();
i++;
}
//System.out.println (usuario);
if(datos[0]==usuario) {
System.out.println ("WORKING");
}
Generally .equals is used for Object comparison, where you want to verify if two Objects have an identical value.
== for reference comparison (are the two Objects the same Object on the heap) & to check if the Object is null. It is also used to compare the values of primitive types.
== operator compares the reference of an object in Java. You can use string's equals method .
String s = "Test";
if(s.equals("Test"))
{
System.out.println("Equal");
}
If you are going to compare any assigned value of the string i.e. primitive string, both "==" and .equals will work, but for the new string object you should use only .equals, and here "==" will not work.
Example:
String a = "name";
String b = "name";
if(a == b) and (a.equals(b)) will return true.
But
String a = new String("a");
In this case if(a == b) will return false
So it's better to use the .equals operator...
The == operator is a simple comparison of values.
For object references the (values) are the (references). So x == y returns true if x and y reference the same object.
I know this is an old question but here's how I look at it (I find very useful):
Technical explanations
In Java, all variables are either primitive types or references.
(If you need to know what a reference is: "Object variables" are just pointers to objects. So with Object something = ..., something is really an address in memory (a number).)
== compares the exact values. So it compares if the primitive values are the same, or if the references (addresses) are the same. That's why == often doesn't work on Strings; Strings are objects, and doing == on two string variables just compares if the address is same in memory, as others have pointed out. .equals() calls the comparison method of objects, which will compare the actual objects pointed by the references. In the case of Strings, it compares each character to see if they're equal.
The interesting part:
So why does == sometimes return true for Strings? Note that Strings are immutable. In your code, if you do
String foo = "hi";
String bar = "hi";
Since strings are immutable (when you call .trim() or something, it produces a new string, not modifying the original object pointed to in memory), you don't really need two different String("hi") objects. If the compiler is smart, the bytecode will read to only generate one String("hi") object. So if you do
if (foo == bar) ...
right after, they're pointing to the same object, and will return true. But you rarely intend this. Instead, you're asking for user input, which is creating new strings at different parts of memory, etc. etc.
Note: If you do something like baz = new String(bar) the compiler may still figure out they're the same thing. But the main point is when the compiler sees literal strings, it can easily optimize same strings.
I don't know how it works in runtime, but I assume the JVM doesn't keep a list of "live strings" and check if a same string exists. (eg if you read a line of input twice, and the user enters the same input twice, it won't check if the second input string is the same as the first, and point them to the same memory). It'd save a bit of heap memory, but it's so negligible the overhead isn't worth it. Again, the point is it's easy for the compiler to optimize literal strings.
There you have it... a gritty explanation for == vs. .equals() and why it seems random.
#Melkhiah66 You can use equals method instead of '==' method to check the equality.
If you use intern() then it checks whether the object is in pool if present then returns
equal else unequal. equals method internally uses hashcode and gets you the required result.
public class Demo
{
public static void main(String[] args)
{
String str1 = "Jorman 14988611";
String str2 = new StringBuffer("Jorman").append(" 14988611").toString();
String str3 = str2.intern();
System.out.println("str1 == str2 " + (str1 == str2)); //gives false
System.out.println("str1 == str3 " + (str1 == str3)); //gives true
System.out.println("str1 equals str2 " + (str1.equals(str2))); //gives true
System.out.println("str1 equals str3 " + (str1.equals(str3))); //gives true
}
}
The .equals() will check if the two strings have the same value and return the boolean value where as the == operator checks to see if the two strings are the same object.
Someone said on a post higher up that == is used for int and for checking nulls.
It may also be used to check for Boolean operations and char types.
Be very careful though and double check that you are using a char and not a String.
for example
String strType = "a";
char charType = 'a';
for strings you would then check
This would be correct
if(strType.equals("a")
do something
but
if(charType.equals('a')
do something else
would be incorrect, you would need to do the following
if(charType == 'a')
do something else
a==b
Compares references, not values. The use of == with object references is generally limited to the following:
Comparing to see if a reference is null.
Comparing two enum values. This works because there is only one object for each enum constant.
You want to know if two references are to the same object
"a".equals("b")
Compares values for equality. Because this method is defined in the Object class, from which all other classes are derived, it's automatically defined for every class. However, it doesn't perform an intelligent comparison for most classes unless the class overrides it. It has been defined in a meaningful way for most Java core classes. If it's not defined for a (user) class, it behaves the same as ==.
Use Split rather than tokenizer,it will surely provide u exact output
for E.g:
string name="Harry";
string salary="25000";
string namsal="Harry 25000";
string[] s=namsal.split(" ");
for(int i=0;i<s.length;i++)
{
System.out.println(s[i]);
}
if(s[0].equals("Harry"))
{
System.out.println("Task Complete");
}
After this I am sure you will get better results.....

Categories

Resources