Object Variables

Introduction

Object variable (reference variable) stores reference to an object, not the object itself.

Student s = new Student();
// s is object variable (reference)
// new Student() creates actual object

Object vs Primitive Variables

Primitive Variable:

int x = 10;  // Stores actual value

Object Variable:

Student s = new Student();  // Stores reference (address)

Memory Representation

Student s1 = new Student("John", 101);
Student s2 = new Student("Alice", 102);

// Stack:           Heap:
// s1 ----->        [Student object: name="John", rollNo=101]
// s2 ----->        [Student object: name="Alice", rollNo=102]

Basic Example

class Student {
    String name;
    int rollNo;

    Student(String name, int rollNo) {
        this.name = name;
        this.rollNo = rollNo;
    }
}

public class Main {
    public static void main(String[] args) {
        // Create object variable
        Student s1 = new Student("John", 101);

        System.out.println(s1.name);    // John
        System.out.println(s1.rollNo);  // 101
    }
}

Null Reference

Object variable with no object.

Student s = null;  // No object assigned

// s.name;  // NullPointerException

if (s != null) {
    System.out.println(s.name);  // Safe
}

Multiple References to Same Object

class Student {
    String name;
    int rollNo;

    Student(String name, int rollNo) {
        this.name = name;
        this.rollNo = rollNo;
    }
}

public class Main {
    public static void main(String[] args) {
        Student s1 = new Student("John", 101);
        Student s2 = s1;  // Both point to same object

        System.out.println(s1.name);  // John
        System.out.println(s2.name);  // John

        // Change through s2
        s2.name = "Alice";

        System.out.println(s1.name);  // Alice (affected!)
        System.out.println(s2.name);  // Alice

        System.out.println(s1 == s2);  // true (same reference)
    }
}

Assignment Behavior

Primitive Types:

int a = 10;
int b = a;  // Copy value

b = 20;
System.out.println(a);  // 10 (unchanged)
System.out.println(b);  // 20

Object Types:

Student s1 = new Student("John", 101);
Student s2 = s1;  // Copy reference

s2.name = "Alice";
System.out.println(s1.name);  // Alice (changed!)
System.out.println(s2.name);  // Alice

Object Variables in Methods

class Student {
    String name;
    int marks;

    Student(String name, int marks) {
        this.name = name;
        this.marks = marks;
    }
}

class Test {
    // Method receives reference
    static void updateMarks(Student s, int newMarks) {
        s.marks = newMarks;  // Changes original object
    }

    static void changeReference(Student s) {
        s = new Student("New", 100);  // Only local reference changes
    }
}

public class Main {
    public static void main(String[] args) {
        Student s1 = new Student("John", 50);

        Test.updateMarks(s1, 95);
        System.out.println(s1.marks);  // 95 (changed)

        Test.changeReference(s1);
        System.out.println(s1.name);  // John (unchanged)
    }
}

Comparing Object Variables

Using == (Reference Comparison):

Student s1 = new Student("John", 101);
Student s2 = new Student("John", 101);
Student s3 = s1;

System.out.println(s1 == s2);  // false (different objects)
System.out.println(s1 == s3);  // true (same reference)

Using equals() (Content Comparison):

Student s1 = new Student("John", 101);
Student s2 = new Student("John", 101);

System.out.println(s1.equals(s2));  // Depends on equals() implementation

Array of Objects

class Student {
    String name;
    int rollNo;

    Student(String name, int rollNo) {
        this.name = name;
        this.rollNo = rollNo;
    }
}

public class Main {
    public static void main(String[] args) {
        // Create array of references
        Student[] students = new Student[3];

        // Initially all null
        System.out.println(students[0]);  // null

        // Create objects
        students[0] = new Student("John", 101);
        students[1] = new Student("Alice", 102);
        students[2] = new Student("Bob", 103);

        // Access objects
        for (Student s : students) {
            System.out.println(s.name + " - " + s.rollNo);
        }
    }
}

Object Variables and Polymorphism

class Animal {
    void sound() {
        System.out.println("Animal sound");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Bark");
    }
}

class Cat extends Animal {
    @Override
    void sound() {
        System.out.println("Meow");
    }
}

public class Main {
    public static void main(String[] args) {
        // Parent reference, child objects
        Animal a1 = new Dog();  // Upcasting
        Animal a2 = new Cat();  // Upcasting

        a1.sound();  // Bark
        a2.sound();  // Meow

        // Array of parent references
        Animal[] animals = new Animal[3];
        animals[0] = new Dog();
        animals[1] = new Cat();
        animals[2] = new Dog();

        for (Animal a : animals) {
            a.sound();  // Polymorphic behavior
        }
    }
}

Complete Example

class BankAccount {
    private String accountNumber;
    private double balance;

    BankAccount(String accountNumber, double balance) {
        this.accountNumber = accountNumber;
        this.balance = balance;
    }

    void deposit(double amount) {
        balance += amount;
    }

    void displayBalance() {
        System.out.println("Account: " + accountNumber);
        System.out.println("Balance: " + balance);
    }
}

public class Main {
    public static void main(String[] args) {
        // Create object variables
        BankAccount acc1 = new BankAccount("A001", 1000);
        BankAccount acc2 = new BankAccount("A002", 2000);

        // Both point to different objects
        acc1.displayBalance();
        acc2.displayBalance();

        System.out.println();

        // acc3 points to same object as acc1
        BankAccount acc3 = acc1;

        acc3.deposit(500);

        // Both affected (same object)
        System.out.println("After deposit through acc3:");
        acc1.displayBalance();  // 1500
        acc3.displayBalance();  // 1500

        // acc2 unchanged (different object)
        acc2.displayBalance();  // 2000
    }
}

Garbage Collection

public class Main {
    public static void main(String[] args) {
        Student s1 = new Student("John", 101);
        Student s2 = new Student("Alice", 102);

        // s1 now points to s2's object
        s1 = s2;

        // Original s1 object (John, 101) has no reference
        // Eligible for garbage collection

        s1 = null;  // s1 reference removed
        s2 = null;  // s2 reference removed
        // Both objects eligible for garbage collection
    }
}

this Keyword

this is a reference to current object.

class Student {
    String name;

    Student(String name) {
        this.name = name;  // this refers to current object
    }

    void display() {
        System.out.println(this.name);  // this.name
        System.out.println(name);       // Same
    }

    Student getThis() {
        return this;  // Return current object reference
    }
}

public class Main {
    public static void main(String[] args) {
        Student s = new Student("John");
        Student s2 = s.getThis();

        System.out.println(s == s2);  // true (same object)
    }
}

Object Variables vs Pointers (C/C++)

Java doesn’t have pointers, but object variables work similarly.

// Java
Student s = new Student();
s.name = "John";

// Similar to C++ pointer
// Student* s = new Student();
// s->name = "John";

Key Differences:

  • No pointer arithmetic in Java
  • Automatic garbage collection
  • Cannot access memory directly
  • Safer than C++ pointers

Immutable Objects

String s1 = "Hello";
String s2 = s1;

s1 = "World";  // Creates new object

System.out.println(s1);  // World
System.out.println(s2);  // Hello (unchanged)

// String is immutable
// s1 = "World" creates new object, doesn't modify original

Pass by Value (Reference)

Java passes reference by value.

class Student {
    String name;
    Student(String name) { this.name = name; }
}

class Test {
    static void modifyObject(Student s) {
        s.name = "Modified";  // ✓ Changes original object
    }

    static void reassignReference(Student s) {
        s = new Student("New");  // ✗ Only local copy changes
    }
}

public class Main {
    public static void main(String[] args) {
        Student s1 = new Student("John");

        Test.modifyObject(s1);
        System.out.println(s1.name);  // Modified

        Test.reassignReference(s1);
        System.out.println(s1.name);  // Modified (unchanged)
    }
}

Quick Reference

// Declaration
Student s;

// Initialization
s = new Student("John", 101);

// Or combined
Student s = new Student("John", 101);

// Null reference
Student s = null;

// Multiple references
Student s1 = new Student("John", 101);
Student s2 = s1;  // Same object

// Array of objects
Student[] students = new Student[3];
students[0] = new Student("John", 101);

// Comparison
s1 == s2     // Reference comparison
s1.equals(s2) // Content comparison

// Check null
if (s != null) {
    s.method();
}

Common Mistakes

Mistake 1: NullPointerException

Student s = null;
// s.name = "John";  // ✗ NullPointerException

// ✓ Correct
if (s != null) {
    s.name = "John";
}

Mistake 2: Expecting Value Copy

Student s1 = new Student("John", 101);
Student s2 = s1;  // Reference copy, not object copy

s2.name = "Alice";
System.out.println(s1.name);  // Alice (not John!)

Mistake 3: Using == for Content

Student s1 = new Student("John", 101);
Student s2 = new Student("John", 101);

// System.out.println(s1 == s2);  // false (different objects)
System.out.println(s1.equals(s2));  // ✓ Correct for content

Real-World Example

class Employee {
    private String name;
    private double salary;

    Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    void raiseSalary(double percent) {
        salary += salary * percent / 100;
    }

    void display() {
        System.out.println(name + ": $" + salary);
    }
}

class Department {
    private Employee manager;
    private Employee[] employees;

    Department(Employee manager) {
        this.manager = manager;  // Store reference
        this.employees = new Employee[10];
    }

    void addEmployee(Employee emp, int index) {
        employees[index] = emp;  // Store reference
    }

    void giveRaises(double percent) {
        manager.raiseSalary(percent);

        for (Employee emp : employees) {
            if (emp != null) {
                emp.raiseSalary(percent);
            }
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Employee mgr = new Employee("John", 50000);
        Employee emp1 = new Employee("Alice", 30000);
        Employee emp2 = new Employee("Bob", 35000);

        Department dept = new Department(mgr);
        dept.addEmployee(emp1, 0);
        dept.addEmployee(emp2, 1);

        System.out.println("Before raise:");
        mgr.display();
        emp1.display();
        emp2.display();

        dept.giveRaises(10);

        System.out.println("\nAfter raise:");
        mgr.display();   // Changed through dept reference
        emp1.display();  // Changed through dept reference
        emp2.display();  // Changed through dept reference
    }
}

Exam Tips

Remember:

  1. Object variable stores reference (address)
  2. Not the actual object
  3. Multiple variables can reference same object
  4. null means no object
  5. == compares references
  6. equals() compares content
  7. Assignment copies reference, not object
  8. Pass by value of reference
  9. Changes through any reference affect same object
  10. NullPointerException when accessing null reference

Common Questions:

  • What is object variable?
  • Object variable vs primitive variable?
  • What is null reference?
  • What happens when multiple variables reference same object?
  • == vs equals()?
  • How are objects passed to methods?
  • What is NullPointerException?
  • How is object variable different from pointer?