37

I am making an archive for my family. There are no syntax errors, however whenever I type in "Maaz", it evaluates realName == "Maaz" to false and goes to the else statement.

import java.util.Scanner;

public class MainFamily {
    public static void main (String [] args) {

        System.out.println("Enter you're name here");
        Scanner name = new Scanner(System.in);//Scanner variable = name

        String realName;
        realName = name.nextLine();//String variable = user input
        System.out.println("Name: "+ realName);

        if (realName == "Maaz") {

            System.out.println("Name: Maaz");

        } else {
            System.out.println("This person is not in the database");
        }
    }
}       
Charles Goodwin
  • 6,402
  • 3
  • 34
  • 63
Maaz Mahmood
  • 379
  • 1
  • 3
  • 5
  • 9
    Use `realName.equals("Maaz");` – President James K. Polk Sep 10 '11 at 23:55
  • 3
    A very good idea was, to mention, that you don't get compile errors, and no exception, but a runtime semantics error, and which. But please read the FAQ about how to write questions, create meaningful headlines which not just repeat the tag `java` and that you're a beginner. Good idea to post the whole source, and use syntax highlightening, but not so good to use slang (plzzz). Avoid greetings and such - nearly every question here is searching for help. In general, be welcome. :) – user unknown Sep 11 '11 at 00:01
  • 1
    @GregS: Don't misuse comments for answers. :) – user unknown Sep 11 '11 at 00:02

12 Answers12

48

TL;DR

You wrote (this doesn't work):

realName == "Maaz"

You meant this:

realname.equals("Maaz")

or this:

realname.equalsIgnoreCase("Maaz")

Explanation

In Java (and many other Object-Oriented programming languages), an object is not the same as a data-type. Data-types are recognized by the runtime as a data-type.

Examples of data-types include: int, float, short.

There are no methods or properties associated with a data-type. For example, this would throw an error, because data-types aren't objects:

int x = 5;
int y = 5;
if (x.equals(y)) {
    System.out.println("Equal");
}

A reference is basically a chunk of memory that explicitly tells the runtime environment what that data-block is. The runtime doesn't know how to interpret this; it assumes that the programmer does.

For example, if we used Integer instead of int in the previous example, this would work:

Integer x = new Integer(5);
Integer y = new Integer(5);
if (x.equals(y)) {
    System.out.println("Equal");
}

Whereas this would not give the expected result (the if condition would evaluate to false):

Integer x = new Integer(5);
Integer y = new Integer(5);
if (x == y) {
    System.out.println("Equal");
}

This is because the two Integer objects have the same value, but they are not the same object. The double equals basically checks to see if the two Objects are the same reference (which has its uses).

In your code, you are comparing an Object with a String literal (also an object), which is not the same as comparing the values of both.

Let's look at another example:

String s = "Some string";
if (s == "Some string") {
    System.out.println("Equal");
}

In this instance, the if block will probably evaluate to true. Why is this?

The compiler is optimized to use as little extra memory as is reasonable, although what that means depends on the implementation (and possibly runtime environment).

The String literal, "Some string", in the first line will probably be recognized as equivalent to the String literal in the second line, and will use the same place in memory for each. In simple terms, it will create a String object and plug it into both instances of "Some string". This cannot be relied upon, so using String.equals is always a better method of checking equivalence if you're only concerned with the values.

kale
  • 151
  • 1
  • 10
beatgammit
  • 19,817
  • 19
  • 86
  • 129
  • Good answer. And for further related information see this question: http://stackoverflow.com/questions/594604/string-equality-vs-equality-of-location – Raedwald Sep 12 '11 at 12:55
  • If I remember correctly, Java has preallocated 0-255 for integers, so all integers with values in that range ARE in fact equal, since they all points to the same object... similarly, final String s1 = "foo"; final String s2 = "foo"; are also equal, since they will be optimized to point to same object. – Per Alexandersson Sep 16 '11 at 19:31
  • @Paxinum - That' what my last code example was trying to say, but I wasn't sure if every runtime/compiler works the same (e.g. OpenJDK, Android's compiler, etc). – beatgammit Sep 16 '11 at 19:58
  • But if the condition like this `String s1 = new String("test"); String s2 = "test";` s1 == s2 will always return false – HendraWD Oct 31 '17 at 08:31
10

do this instead

if (realName.equals("Maaz"))

equals() should be used on all non-primitive objects, such as String in this case

'==' should only be used when doing primitive comparisons, such as int and long

Shawn
  • 7,235
  • 6
  • 33
  • 45
10

use

if(realName.equals("Maaz"))

use == with primitive data type like int boolean .... etc

but if you want to compare object in java you should use the equals method

confucius
  • 13,127
  • 10
  • 47
  • 66
7

You have to compare objects with realName.equals ("Maaze"), not with ==.

user unknown
  • 35,537
  • 11
  • 75
  • 121
6

It is best practice to compare Strings using str.equals(str2) and not str == str2. As you observed, the second form doesn't work a lot of the time. By contrast, the first form always works.

The only cases where the == approach will always work are when the strings are being compared are:

  • string literals or references to string literals, or
  • strings that have been "interned" by application-level code calling str = str.intern();.

(And no, strings are not interned by default.)

Since it is generally tricky to write programs that guarantee these preconditions for all strings, it is best practice to use equals unless there is a performance-related imperative to intern your strings and use ==.

Before that you decide that interning is a good idea, you need to compare the benefits of interning with the costs. Those costs include the cost of looking up the string in the string pool's hash table and the space and GC overheads of maintaining the string pool. These are non-trivial compared with the typical costs of just using a regular string and comparing using equals.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • For the sake of completeness: string-valued constant expressions like "hello " + "world" behave the same way as string literals in this case. – johncip Mar 02 '13 at 12:27
  • @JohnC - that is true, but it is (IMO) not relevant to either the Question or my Answer. Especially since the **main message** of my Answer is to NOT use `==` to compare strings. – Stephen C Mar 04 '13 at 04:01
4

You can also use

realname.equalsIgnoreCase("Maaz")

This way you can accept Maaz, maaz, maaZ, mAaZ, etc.

David Moreno García
  • 4,423
  • 8
  • 49
  • 82
3

== tests shallow equality. It checks if two objects reference the same location in memory.

ben
  • 472
  • 1
  • 3
  • 10
  • `==` tests for *instance* equality. That it *might* do that by comparing memory locations is an implementation detail of some JVMs and not necessarily true. – Philipp Reichart Sep 16 '11 at 19:24
2

Intriguing. Although, as others have stated, the correct way is to use the .equals(...) method, I always thought strings were pooled (irrespective of their creation). It seems this is only true of string literals.

final String str1 = new String("Maaz");
final String str2 = new String("Maaz");
System.out.println(str1 == str2); // Prints false

final String str3 = "Laaz";
final String str4 = "Laaz";
System.out.println(str3 == str4); // Prints true
hoipolloi
  • 7,984
  • 2
  • 27
  • 28
  • 3
    Equality of String literals is well-known and well-defined in the JLS, chapter 3.10.5: [String Literals](http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.5). – Bombe Sep 11 '11 at 00:59
  • 1
    The first part tests the identity(location) of `str1` and `str2` and so they do not point to the same location in memory. The second part tests the string literals and does test their value (this is where the pooling/interning comes into play. – non sequitor Sep 11 '11 at 01:12
  • 3
    @non - Huh? Both parts do *exactly the same thing*. String literals are interned and therefore `str3` and `str4` have the same value; they both point to the same place in memory. – Brian Roach Sep 11 '11 at 01:34
  • @non == for objects compares the reference values. I agree with Brian. – Ankur Agarwal Sep 11 '11 at 02:54
0
if(realName.compareTo("Maaz") == 0) {
    // I dont think theres a better way do to do this.
}
Felype
  • 3,087
  • 2
  • 25
  • 36
0

Since you are working on strings, you should use equals to equalsIngnorecase method of String class. "==" will only compare if the both objects points to same memory location, in your case, both object are different and will not be equal as they dont point to same location. On the other hand, equals method of String class perform a comparison on the basis of the value which objects contains. Hence, if you will use equals method, your if condition will be satisfied.

farooq.ind
  • 11
  • 2
0

== compares object references or primitive types (int, char, float ...)

equals(), you can override this method to compare how both objects are equal.

for String class, its method equal() will compare the content inside if they are the same or not.

If your examples, both strings do not have the same object references, so they return false, == are not comparing the characters on both Strings.

TheOneTeam
  • 25,806
  • 45
  • 116
  • 158
0

It seems nobody yet pointed out that the best practice for comparing an object with a constant in Java is calling the equals method of the constant, not the variable object:

if ("Maaz".equals (realName)) {}

This way you don't need to additionally check if the variable realName is null.

Andrei LED
  • 2,560
  • 17
  • 21
  • [There are no Best Practices](https://www.satisfice.com/blog/archives/5164). In circumstances where the `realName` is `null` is a symptom of a bug, then you *want* the NPE to happen so that you know the bug is there. In that scenario, this (so called) best practice is not the correct solution. Ergo, it is NOT best practice at all. – Stephen C Feb 04 '21 at 08:43