== — compares memory addresses (same object?). .equals() — compares content (same data?).Simple analogy: Two identical houses on the same street. == asks: "Is this the EXACT same house?" (same address). .equals() asks: "Do these houses look the same?" (same paint color, rooms). Two houses can look identical but have different addresses.Why it matters: Using == instead of .equals() for object comparison is one of the most common bugs in Java. It causes tests that pass sometimes and fail other times due to String pooling.Common mistakes:- Using == to compare String content — works sometimes (pool) but fails with new String().- Forgetting to override equals() in custom classes.- Overriding equals() without overriding hashCode() — breaks HashMap/HashSet.For primitives:javaint a = 5;int b = 5;a == b; // true — same value// Primitives don't have .equals()For objects:javaString s1 = new String("hello");String s2 = new String("hello");s1 == s2; // false — different objectss1.equals(s2); // true — same contentString pool gotcha:javaString s1 = "hello"; // String poolString s2 = "hello"; // Same pool references1 == s2; // true!String s3 = new String("hello"); // New objects1 == s3; // falses1.equals(s3); // trueString s4 = "hel" + "lo"; // Compiler constant foldings1 == s4; // true — optimizedString s5 = "hel";String s6 = s5 + "lo"; // Runtime concat — new objects1 == s6; // falseOverride equals() correctly:javapublic class Person { private String name; private int age; @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Person other = (Person) obj; return age == other.age && Objects.equals(name, other.name); } @Override public int hashCode() { return Objects.hash(name, age); }}Best practice: Always use .equals() for content comparison. Reserve == for null checks and reference identity.