AP Computer Science A
One-page, printable cheatsheet
Cheatsheet visualization
Find gaps with guided practice
Guided practice grid visualization
Table of Contents

💻ap computer science a review

3.7 Comparing Objects

Verified for the 2025 AP Computer Science A examCitation:

In Java, comparing values is a fundamental operation that works differently depending on the type of data you're working with. While comparing primitive types like int or double is straightforward, comparing objects requires a deeper understanding of how Java handles references and equality. This guide will explore the nuances of comparing object references, understanding aliasing, and using methods like equals() to determine when two objects contain the same data. Mastering these concepts will help you avoid subtle bugs and write more reliable code.

Primitive vs. Reference Types

Before diving into object comparison, let's clarify the difference between primitive and reference types:

Primitive Types

  • Basic data types like int, double, boolean, and char
  • Store actual values directly in memory
  • Compared using equality operators (==, !=)
  • Always behave predictably when compared

Reference Types (Objects)

  • Everything that isn't a primitive (Strings, arrays, and instances of classes)
  • Store references (addresses) to objects in memory, not the actual objects
  • When using == or !=, you're comparing memory addresses, not content
  • Need special methods for content comparison

Object References and Aliases

When you create an object in Java, what you're actually working with is a reference to that object's location in memory. When two variables reference the same object, they are called aliases.

// Two references to the SAME object (aliasing)
Student student1 = new Student("Alex");
Student student2 = student1;

// Two references to DIFFERENT objects with the same data
Student student3 = new Student("Alex");
Student student4 = new Student("Alex");

In this example:

  • student1 and student2 are aliases (they reference the same object)
  • student3 and student4 reference different objects (even though they contain the same data)

Comparing Object References with == and !=

The equality operators == and != compare whether two references point to the same object in memory:

// Continuing from the example above
boolean sameReference1 = (student1 == student2); // true - same object

boolean sameReference2 = (student1 == student3); // false - different objects

This diagram illustrates what's happening in memory:

Memory:
│                  │
│  ┌──────────┐    │    ┌──────────┐
│  │  Student │    │    │  Student │
│  │ name="Alex" │  │    │ name="Alex" │
│  └──────────┘    │    └──────────┘
│       ▲          │         ▲
│       │          │         │
│   student1       │     student3
│   student2       │     student4
│                  │

The null Reference

An object reference can be null, which means it doesn't reference any object. You can check if a reference is null using == or !=:

Student student = null;

if (student == null) {
    System.out.println("No student assigned yet");
}

// Or equivalently
if (student != null) {
    System.out.println("Student name: " + student.getName());
} else {
    System.out.println("No student assigned yet");
}

Trying to call a method on a null reference will result in a NullPointerException, so this check is important for preventing runtime errors.

Content Comparison with equals()

To check if two distinct objects contain the same data, Java provides the equals() method:

String str1 = new String("Hello");
String str2 = new String("Hello");

boolean sameReference = (str1 == str2);  // false - different objects

boolean sameContent = str1.equals(str2); // true - same content

The equals() method is defined in the Object class (the parent class of all Java classes) but is often overridden by subclasses to provide meaningful comparison:

  • The default implementation in Object compares references (same as ==)
  • Classes like String, Integer, and ArrayList override it to compare content
  • For your custom classes, you should override equals() to define what makes two instances equal

String Comparison

Strings require special attention because they're commonly used and often compared:

// Different ways to create String objects
String str1 = "Hello";              // String literal (special case in Java)
String str2 = "Hello";              // Another reference to the same string literal
String str3 = new String("Hello");  // Explicitly creating a new String object

// Comparing references
boolean test1 = (str1 == str2);     // true - Java reuses string literals

boolean test2 = (str1 == str3);     // false - different objects

// Comparing content
boolean test3 = str1.equals(str3);  // true - same content

For Strings, always use equals() for comparison unless you specifically need to check if two variables reference the exact same String object.

Implementing equals() in Your Classes

When creating your own classes, you should override the equals() method to provide meaningful content comparison:

public class Student {
    private String name;
    private int id;
    
    // Constructor and other methods...
    
    @Override
    public boolean equals(Object obj) {
        // Check if the object is compared with itself
        if (this == obj) return true;
        
        // Check if the object is null or different class
        if (obj == null || getClass() != obj.getClass()) return false;
        
        // Cast to the appropriate type
        Student other = (Student) obj;
        
        // Check the relevant fields for equality
        return id == other.id && 
               (name == null ? other.name == null : name.equals(other.name));
    }
}

A proper equals() implementation should:

  • Be reflexive: a.equals(a) should return true
  • Be symmetric: a.equals(b) should return the same as b.equals(a)
  • Be transitive: if a.equals(b) and b.equals(c), then a.equals(c)
  • Be consistent: multiple calls should return the same result if nothing changes
  • Return false when comparing with null

Common Pitfalls When Comparing Objects

1. Using == Instead of equals()

// INCORRECT for content comparison
if (studentName == "John") {
    // This might not work as expected
}

// CORRECT for content comparison
if (studentName.equals("John")) {
    // This will work correctly
}

2. Not Checking for null Before Calling equals()

// RISKY - may cause NullPointerException

if (student.getName().equals("John")) {
    // ...
}

// SAFER - check for null first

if (student != null && "John".equals(student.getName())) {
    // ...
}

// Note: Putting the string literal first prevents 
// NullPointerException even if student.getName() is null

3. Assuming All Classes Override equals()

Not all classes override equals() to compare content. If you're using a class that doesn't (or you're unsure), check the documentation or implementation.

Practical Examples

Example 1: Student Registration System

// Check if a student is already registered
public boolean isStudentRegistered(Student student) {
    for (Student registeredStudent : registeredStudents) {
        // Use equals() to check if a student with the same ID is already registered
        if (registeredStudent.equals(student)) {
            return true;
        }
    }
    return false;
}

Example 2: Shopping Cart Item Comparison

// Check if an item is already in the cart
public boolean isItemInCart(Item newItem) {
    for (Item cartItem : shoppingCart) {
        // Two items might be different objects but represent the same product
        if (cartItem.getProductId() == newItem.getProductId()) {
            return true;
        }
    }
    return false;
}

Key Takeaways

  • The == and != operators compare object references (memory addresses), not content
  • Two object references are aliases when they point to the same object
  • Use the equals() method to compare the content of objects
  • The null reference doesn't refer to any object and can be checked with == or !=
  • String comparison should almost always use equals() instead of ==
  • When creating custom classes, override equals() to define meaningful equality

Understanding the difference between reference equality and content equality is crucial for writing robust Java programs. Always be mindful of whether you need to compare objects by their identity (using ==) or by their content (using equals()), and choose the appropriate approach for your specific requirements.

Key Terms to Review (2)

Equals(): The equals() method is used to compare two objects for equality. It checks if the values of the objects are the same, rather than comparing their memory addresses.
Primitive Types: Primitive types are basic data types in programming that are built-in and cannot be broken down into smaller components. They represent simple values like numbers, characters, and boolean values.