Short answer
== compares references (are these the same object), not contents.
Explanation
String literals are interned into a shared pool, so "a"=="a" happens to be true, which lures beginners into thinking == compares text. But new String("a") == "a" is false, and any runtime-built string (concatenation, input, StringBuilder.toString()) is a distinct object, so == fails. Always use equals() for content, or equalsIgnoreCase() to ignore case.
Common mistakes
- Comparing strings with ==.
- Relying on interning for correctness.