== compares references (memory addresses). equals() compares content/values.
Analogy: == asks "are these two ID cards pointing to the exact same person?" equals() asks "do these two ID cards have the same name, birthday, and photo?"
== operator:
equals() method:
Object class — default is == (reference equality).1// String with new keyword (creates separate objects)2String s1 = new String("hello");3String s2 = new String("hello");45s1 == s2; // FALSE — different objects in memory6s1.equals(s2); // TRUE — same content78// String literals (stored in string pool)9String s3 = "hello";10String s4 = "hello";1112s3 == s4; // TRUE — same object in string pool!13s3.equals(s4); // TRUE — same content1415// Primitives16int a = 5;17int b = 5;18a == b; // TRUE — compares values directly
Overriding equals() correctly:
1class Person {2 private String name;3 private int age;45 public Person(String name, int age) {6 this.name = name;7 this.age = age;8 }910 @Override11 public boolean equals(Object obj) {12 if (this == obj) return true; // Same reference13 if (obj == null || getClass() != obj.getClass()) return false; // Null or wrong class14 Person other = (Person) obj;15 return this.age == other.age16 && Objects.equals(this.name, other.name); // Null-safe comparison17 }1819 @Override20 public int hashCode() {21 return Objects.hash(name, age);22 }23}2425Person p1 = new Person("Alice", 30);26Person p2 = new Person("Alice", 30);27p1 == p2; // FALSE — different objects28p1.equals(p2); // TRUE — content is equal
Critical rule: equals() + hashCode() contract:
equals(), you must override hashCode().1// WRONG: overriding equals() without hashCode()2Set<Person> set = new HashSet<>();3set.add(new Person("Alice", 30));4set.add(new Person("Alice", 30));5set.size(); // 2 — WRONG! hashCode differs, so HashSet treats them as different67// RIGHT: with both equals() and hashCode()8Set<Person> set2 = new HashSet<>();9set2.add(new Person("Alice", 30));10set2.add(new Person("Alice", 30));11set2.size(); // 1 — correct! hashCode is same, equals() returns true
Common mistakes:
== when you need value equality.equals() on primitives (primitives don't have methods — use ==).equals() without overriding hashCode().null in equals() (always handle null).instanceof instead of getClass() (allows subclasses to be equal to parent class).