581

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");
    }
}
codeforester
  • 39,467
  • 16
  • 112
  • 140
franvergara66
  • 10,524
  • 20
  • 59
  • 101
  • 2
    Have a look at this http://www.thejavageek.com/2013/07/27/string-comparison-with-equals-and-assignment-operator/ – Prasad Kharkar Sep 26 '13 at 12:38
  • 3
    "==" compares reference and not the content.Change datos[0] == usuario to datos[0].equals(usuario) to get the correct answer – mani deepak Jan 27 '14 at 08:28
  • 2
    I see you changed your accepted answer - I urge you to read my comments on that and reconsider. The "story" in the now accepted answer might look good initially, but IMHO it really doesn't bear scrutiny. – Alnitak Jul 18 '14 at 19:46
  • Most language work this way, you just don't see it because most languages have operator overloading and the == operator for strings has been overloaded to call the languages equivalent of string.equals. Java doesn't have operator overloading, so you have to do it the hard way, like a cave man. Java also doesn't complain or warn you when comparing strings in this way, so it becomes a runtime error that you get to hunt down. Why doesn't Java have operator overloading? Because they wanted to keep the language simple, then they realised it was too simple and made working with dates complicated. – LordWabbit Sep 05 '20 at 05:03

20 Answers20

606

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.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • 10
    @mo: It isn't equally handled, as you can see by this example. – user unknown May 16 '12 at 14:37
  • 57
    @mo in some cases even in java == can be misleading. Java caches strings and so something like this would return true. `String a = "Hello"; String b = "Hello"; a == b is true` even though one would normally expect the result to be false. – Jon Taylor Jul 24 '12 at 14:19
  • 7
    @JonTaylor Your example has nothing to do with caching. Typing "Hello" in java code actually creates an anonymous static String object in the class. If you are using a good compiler, multiple occurrences of "Hello" *might* use the same static String object, but it would be equally valid to replace "Hello" with `new String(new char[] {'H', 'e', ...})` – parasietje Sep 19 '13 at 09:46
  • 1
    @JonTaylor 's comment seems to contradict Alnitak's answer. Alnitak says you can't compare the contents of Strings with "==", while Jon says you can. Who's right? – trusktr Oct 05 '13 at 08:47
  • 4
    @trusktr you can only use `==` to compare strings that have been "interned" - typically that's string constants. – Alnitak Oct 05 '13 at 14:09
  • 10
    @parasietje The JLS guarantees that multiple occurrences of "Hello" (as a literal) refer to the same String object. A compiler can't replace it with something else. – fgb Oct 05 '13 at 14:41
  • @parasietje my use of the term "cache" may have been incorrect, I was using it more as a concept. My comment still stands correct even if the term itself was incorrect. – Jon Taylor Oct 09 '13 at 13:25
  • The instance method is .equals(Object myObject) in the Java 8 documentation. There is no .equals(String myString). Does the selected answer need an edit? – H2ONaCl Apr 01 '16 at 00:23
  • @H2ONaCl yeah, good call! – Alnitak Apr 01 '16 at 09:08
  • 5
    Be very careful using `==` to compare strings, unless both were initialised with literals `==` will always return false. For example, this will print **false**: `String a = "abc"; String b = "abcd"; a += "d"; System.out.println(a == b);` – Galax May 19 '16 at 21:06
  • 1
    @Galax `==` will also work fine if you have called `intern()` on your strings. – NickL Aug 09 '17 at 19:17
  • I was trying below example to understand it deeper `String x = "o";//line-1 ` `String a = "Hell" + x; ` `String b = "Hello"; ` `System.out.println(a == b);//line-4 ` `String a1 = "Hell" + "o"; ` `String b1 = "Hello"; ` `System.out.println(a1 == b1);//line-7 ` Why do lines 4 and 5 evaluate to two different results? If `String x = "o";` is declared as `final String x = "o";` both lines 4 and 5 print true Could someone please explain or point to a resource to understand this example better? – JavaHopper Jan 26 '23 at 07:06
  • Understood from this answer https://stackoverflow.com/a/11989353 Only string literals are pooled. String created at runtime are not. That explains why final gets replaced during compile time and results in true in the example above – JavaHopper Jan 28 '23 at 19:47
592

Meet Jorman

Jorman is a successful businessman and has 2 houses.

enter image description here

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:

enter image description here

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:

enter image description here

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.

Jops
  • 22,535
  • 13
  • 46
  • 63
  • 27
    I love intuitive examples and this is one of the best I've ever seen. Novice programmers can easily understand what's going behind the scenes reading this. – Nader Ghanbari May 04 '14 at 09:18
  • 15
    I actually think this answer is _really_ confusing because it conflates the person's _name_ with the _person themself_. It also confuses "equality" with "equivalence". The `this == anObject` check is semantically _exactly_ a test that one is comparing the same two objects (equality), which by definition therefore must be equivalent. The final `return true` after the `while` loop does _not_ mean we have the _same_ "Jorman", it means the that the two entities share the same value (equivalent) which does _not_ imply equality. (The Java `.equals` method is misnamed in this regard). – Alnitak Jul 18 '14 at 19:40
  • 1
    This answer is for newbies, the next answer, the one by Michal Bernhard provides the correct analysis of Java's inconsistent behavior of == when applied to string. – Gsv Oct 24 '14 at 04:35
  • 3
    @DavidT. you forgot the check for fingerprints :) – Raymond Chenon May 20 '15 at 14:46
  • 2
    `-1` since [no hand drawn red circles](http://meta.stackexchange.com/a/19775/255942) - and seriously, `+1` for the Jorman guy. –  Jan 14 '16 at 20:42
  • 1
    This analogy works for demonstrating `==` (reference equality). But it is not a good analogy for demonstrating `string.equals()` (value equality/equivalence), because Jorman is only one person and the same person. To properly demonstrate `string.equals()`, the analogy should be to compare all the attributes of the 2 houses (dimensions, color, etc). If they all match, then they are equivalent (`string.equals()==true`), even though they are 2 separate houses. – wisbucky Feb 14 '18 at 21:57
  • Point grasped easily. Thanks for taking the time to illustrate this very well. – Strategist Mar 30 '18 at 05:34
  • 1
    Somewhere I read equality and equivalence being summarised in this sentence: Equality means "a is b". Equivalence means "a is like b" In an attempt to apply the same sentence to the above example: Equality means "Jornam living at Madison Street is the same person as Jornam living at Burke Street". Equivalence means "Someone named Jornam living at Madison Street is like someone named Jornam living at Burke Street " – panza Jun 06 '18 at 11:48
  • THX, So surprise... – BertKing Jul 23 '19 at 11:37
102

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

DarkAjax
  • 15,955
  • 11
  • 53
  • 65
Michal Bernhard
  • 3,853
  • 4
  • 27
  • 38
  • 6
    It's actually not just a side effect of jvm optimization and has nothing to do with the compiler at all. The identity of static strings (literals) across all classes is guaranteed according to the Java VM Specification and works with every VM that is at least Java 1.1 compatible. – x4u Feb 06 '10 at 07:20
  • 7
    If you mean JVM spec chapter 2.3 "String literals and, more generally, strings that are the values of constant expressions are "interned" so as to share unique instances, using the method String.intern". Well it's guaranteed by jvm (according to spec), but for me this still means optimization. There is no semantic value of this AFAIK. On the other hand == has semantic "identity equality" and method equals() has "object equality" so you should obey this and no rely on jvm specification, which is "guide" for jvm implementators rather then for developers (they have Java Language Specification). – Michal Bernhard Jul 14 '11 at 21:07
  • 3
    The literals, classnames and the likes are interned to comply with the spec, it's not mere optimization. "xxx" is always == "xxx", this is part of the language design not an impl. detail/guideline. – bestsss Jun 07 '12 at 12:52
  • 1
    Actually, using == always returns the expected result. The problem is in some people having wrong expectations about the result. This is not a problem of the language, rather of their lack of knowledge. If they expect == to always return the same as the result of .equals, they should re-read their textbook. If, on the other hand, they expect == to return a comparison of reference, they'll notice it'll always return what they expect. – Stultuske May 08 '15 at 07:18
38
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.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Aniket Thakur
  • 66,731
  • 38
  • 279
  • 289
  • This is the simplest answer and clearly demonstrates the different cases. – wisbucky Feb 14 '18 at 22:12
  • 1
    I would 2 more examples to Case2: `s1 == "Stack Overflow" // false` and `s1.equals("Stack Overflow") // true`. That demonstrates comparing object to literal. – wisbucky Feb 14 '18 at 22:30
38

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.

jiaweizhang
  • 809
  • 1
  • 11
  • 28
HariShankar
  • 859
  • 1
  • 10
  • 21
  • I'm wondering, in what (non-obvious) case will abc == xyz work? – Chibueze Opata Mar 11 '12 at 14:21
  • 7
    The code outputs (after fixing prinln to println): Refers to same string, Contents of both strings are same i.e. here both (abc == xyz) and (abc.equals(xyz)) are true! – arun Oct 24 '12 at 23:15
  • 6
    as mentioned above this answer is wrong. because of intern optimization mechanisms sometimes 2 string objects with the same content are actually represented by only one object. this optimization is possible because strings are immutable – tObi Sep 15 '13 at 16:23
  • https://stackoverflow.com/a/513839/1889167 is having the detailed answer! – mavis Oct 25 '17 at 17:16
29

== 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.

jiaweizhang
  • 809
  • 1
  • 11
  • 28
Puneet Purohit
  • 1,243
  • 6
  • 23
  • 42
  • this is the most simple answer I have seen for this question so far.. thank you. – Swadhikar Jul 06 '16 at 10:55
  • Concerning substrings, if you use == with identical strings and one of them is a substring of the other, then == will return true. For example, this (at least when I tested it) prints true: `String str = "abcdef"; System.out.println(str == str.substring(0, str.length()));` – MinteZ Aug 17 '17 at 18:24
26

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.

Jeff Atwood
  • 63,320
  • 48
  • 150
  • 153
Bhushan Bhangale
  • 10,921
  • 5
  • 43
  • 71
  • 11
    just make sure the left side isn't null – Steve Kuo Apr 20 '09 at 14:55
  • or use usario.equals instead, like the selected answer by @Alnitak demonstrates. It saves you a step (or a whole bunch) if you initially know usario isn't null. –  Nov 06 '12 at 14:33
12

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
jiaweizhang
  • 809
  • 1
  • 11
  • 28
Harry He
  • 1,795
  • 16
  • 12
  • You aren't supposed to override equals for your classes. You might do, and in some cases you should do so. Why would I overwrite equals in my XyPanel, in a FooDialog? – user unknown May 16 '12 at 14:40
11

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");    
}
finnw
  • 47,861
  • 24
  • 143
  • 221
11

You should use string equals to compare two strings for equality, not operator == which just compares the references.

Michael Klement
  • 3,376
  • 3
  • 30
  • 34
9

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...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mreaevnia
  • 578
  • 2
  • 6
  • 15
8

== 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");
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Himanshu Mohta
  • 1,033
  • 9
  • 15
8

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.

jiaweizhang
  • 809
  • 1
  • 11
  • 28
Abhinav Jayaram
  • 156
  • 1
  • 4
6

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.

engy
  • 141
  • 2
  • 4
6

@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
  }
}

tinker_fairy
  • 1,323
  • 1
  • 15
  • 18
6

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.

Raekye
  • 5,081
  • 8
  • 49
  • 74
4

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.

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
Dinoop Nair
  • 2,663
  • 6
  • 31
  • 51
4

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
Keith Spriggs
  • 235
  • 1
  • 4
  • 10
4

a==b

Compares references, not values. The use of == with object references is generally limited to the following:

  1. Comparing to see if a reference is null.

  2. Comparing two enum values. This works because there is only one object for each enum constant.

  3. 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 ==.

jiaweizhang
  • 809
  • 1
  • 11
  • 28
rohan kamat
  • 583
  • 5
  • 12
3

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.....

Harrydev
  • 49
  • 1