-2

This question has been asked before, but not really answered.

If the substring method creates a new object, and this is object is "interned" in the pool, then why does the == return false. Here's my code:

public class StringTest {
    public static void main(String[] args) {
        String str1 = "The dog was happy";
        String str2 = "The hog was happy";
        System.out.println(str1.substring(5));// just to make sure
        System.out.println(str2.substring(5));

        if (str1.substring(5) == str2.substring(5)) {
            System.out.println("Equal using equality operator");
        } else {
            System.out.println("Not equal using equality operator");
        }

        if (str1.substring(5).equals(str2.substring(5))) {
            System.out.println("Equal using equals method");
        } else {
            System.out.println("Not equal using equals method");
        }

    }
}

Output is: 1. og was happy 2. og was happy 3. Not equal using equality operator 4. Equal using equals method

P.S. This is the substring method source code:

public String substring(int beginIndex, int endIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > count) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    if (beginIndex > endIndex) {
        throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
    }
    return ((beginIndex == 0) && (endIndex == count)) ? this :
        new String(offset + beginIndex, endIndex - beginIndex, value);
}

P.S. This question has been marked as asked and answered by several people, yet I could not find one single instance on Stack Overflow where someone actually explained why substring(0) will evaluate to true.

A_W
  • 53
  • 1
  • 7
  • You did not `intern` the substrings. `str1.substring(5).intern() == str2.substring(5).intern()`. – tsolakp Feb 02 '18 at 20:58
  • @Apollonius. No. – tsolakp Feb 02 '18 at 21:12
  • *and this is object is "interned" in the pool* ... Do you think that happens automatically? Why? – Tom Feb 02 '18 at 21:51
  • Thank you for your replies. My confusion stems from the problem statement here (https://stackoverflow.com/questions/21606800/string-equality-using-replace-and-substring-methods) and the answers to it. Like I said, I had to answer a very similar exam question (I'm a student), and I am not entirely sure I understand it. I understand that the substring() method will create 2 different objects, therefore the ==operation will fail, but I do not understand why in said question Statement 1 is true, but Statement 2 is not true. Obviously, I'm missing something. – A_W Feb 03 '18 at 14:22
  • I finally found the answer to the odd behaviour, and I'm posting it here for others who might have the same problem. The substring() method (which was changed in Java 7), will always return a new object. The only exception to this is if it is to return the whole string (substring(0)). Then, it will return it from the pool and the equality expression (==) will evaluate to true. – A_W Feb 04 '18 at 00:50
  • @tsolakp Do not advise people to intern strings. That is entirely unnecessary, and in some cases even a bad thing to do. – Mark Rotteveel Feb 07 '18 at 16:37
  • @ Mark Rotteveel. That comment was in the context of question about how interned strings work as an example. If it was some type of question about actual application code then I agree with your comment. – tsolakp Feb 07 '18 at 17:33

1 Answers1

2

Answer lies in your question itself .

Try doing the following:

String str1 = "The dog was happy";
 String str2 = "The dog was happy";
 if (str1 == str2) 
 {
    System.out.println("Equal using equality operator");
 } 
  else 
 {
      System.out.println("Not equal using equality operator");
 }

You will get "Equal using equality operator". Reason being you have declared str1 and str2 both as string literal and there the concept of interned pool applies.

Now when you do str1.substring(5) as per the String class definition it returns an object, not a literal. Hence == gives false result.

String class Substring method:

return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);

If you wants the == to work on substring, please use intern() method on your substrings.

Change: if (str1.substring(5) == str2.substring(5))

to

if (str1.substring(5).intern() == str2.substring(5).intern())

One nice doc to understand details of String creation and pooling: https://www.journaldev.com/797/what-is-java-string-pool

Priya Jain
  • 795
  • 5
  • 15
  • I understand. Substring creates two different objects, hence the equality operator fails. Thank you! – A_W Feb 02 '18 at 21:12