What is the difference between equals and == when comparing Strings in Java?
== compares references: it asks whether the two variables point at the same object. equals compares contents: it asks whether the two objects hold the same sequence of characters. For Strings those two questions have different answers, which is why the distinction matters.
The trap is that == appears to work for a long time. Two literals with the same text usually come from the constant pool and are the same object, so == returns true. The moment a String comes from somewhere else — a database column, a request parameter, a file, a computed value — it is a separate heap object, and == returns false even though the text is identical.
public class Main {
public static void main(String[] args) {
String a = new String("tutorsbot");
String b = new String("tutorsbot");
System.out.println("a == b : " + (a == b)); // false
System.out.println("a.equals(b) : " + a.equals(b)); // true
String c = "tutorsbot";
String d = "tutorsbot";
System.out.println("c == d : " + (c == d)); // true, pooled
System.out.println("c.equals(d) : " + c.equals(d));
// equals is case sensitive, and safe on the receiver.
System.out.println("case sensitive : " + c.equals("TUTORSBOT"));
System.out.println("null receiver : " + "x".equals(null));
}
}Two details about equals itself. It is case sensitive, so c.equals("TUTORSBOT") is false; use equalsIgnoreCase if you want case folding. And it is null-safe on the receiver only — calling a.equals(b) throws a NullPointerException if a is null, whereas b.equals(a) is safe. That asymmetry is why code often does a null check before comparing.
The house rule is simple and worth stating without hesitation in an interview: compare Strings with equals, never with ==. If you want to compare against a literal, use "expected".equals(value) so that a null value cannot blow up the comparison.