-3

(true or false)Suppose String objects b and c contain the same sequence of characters. Then b == c is true.

public static void main(String[] args) {
    String a = "abc";
    String b = "abc";

    System.out.println(a == b);
    System.out.println(a.equals(b));
}

The result is true, but the answer to the question is false. I was wondering why.

Alex
  • 51
  • 4
  • 1
    Basically, coincidentally due to string pooling, "abc" == "abc", but in general, strings cannot be compared using `==` since that operator checks if the two variables point at the same memory location, rather than asserting anything about the contents at that location. – CollinD Aug 05 '18 at 21:52
  • 1
    String literals (with `"`) are **always** stored in an internal string cache. This is called [string interning](https://en.wikipedia.org/wiki/String_interning) and required by the JLS (Java Language Specification). Java must check the cache and see if there is already such an instance. If so, it will use the cached instance. Thus your first `"abc"` triggers the creation of a new `String` with content `abc`. The second will be drawn out of the cache. Thus both refer to the same instance. If you create them without literals, `==` will likely be `false`, even if both have the same content. – Zabuzard Aug 05 '18 at 21:58

2 Answers2

4
public static void main(String[] args) {
    String a = new String("abc");
    String b = new String("abc");

    System.out.println(a.equals(b));
    System.out.println(a == b);
}

Prints true, then false. So two strings with the same sequence of characters do have to equal each other, but can either == each other or not.

Obviously, a == a under all circumstances, and a is a String containing the same sequence of characters as a.

But in the example above, we're creating two different instances, which just happen to contain the same sequence of characters. Hence a != b.

So what's happening in your example? String interning.

Any string literals are allocated in a special pool by the compiler, and any duplicate literals share the same reference. So even though the literal is defined twice, as far as the compiler's concerned, they're the same instance.

Logan
  • 926
  • 1
  • 10
  • 18
Tom Johnson
  • 220
  • 1
  • 7
3

The reason your test results in true is a very weird thing that the JVM likes to do. Because you've defined two String literals, the JVM will just decide to store one of those values, and have both a and b refer to the same string. This is why doing == comparison results in true.

As someone else stated, doing String b = new String("abc"); will force a new String literal to be made, which would be a separate block of memory. Thus == comparison would result in false.

Logan
  • 926
  • 1
  • 10
  • 18
SaxyPandaBear
  • 377
  • 1
  • 6
  • 3
    A bit odd to call this "*very weird thing*". String interning is defined and required in the JLS. Every valid JVM implementation needs to do this. – Zabuzard Aug 05 '18 at 21:56
  • I think it's kind of weird, mostly because I ran into the same confusion as OP when I was learning Java. I wasn't taught about string interning when I was learning. Also don't recall it being something to know for the associate cert exam. I dunno – SaxyPandaBear Aug 05 '18 at 22:00
  • 1
    It is a common optimization. And, as said, required by the JLS. But I get that it confuses beginners. It is one of the most common beginner mistakes. Right next to using `Scanner` wrong :) – Zabuzard Aug 05 '18 at 22:01